2020-01-08 14:32:46 +01:00
[
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"type" : "tab" ,
"label" : "Main" ,
"disabled" : false ,
"info" : ""
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "RPi Monitoring" ,
"info" : "" ,
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#87A980" ,
"icon" : "node-red/status.svg"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "130e0533.4f1813" ,
2020-07-14 18:27:49 +02:00
"type" : "subflow" ,
"name" : "Acquisition actuation" ,
"info" : "" ,
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"color" : "#A6BBCF" ,
"icon" : "font-awesome/fa-camera"
2020-01-08 14:32:46 +01:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1bc3f9f9.1ee996" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Acquisition inputs" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 40 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8887f3e7.e79b5"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "14be4afa.2ba67d"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "600c2b46.83db14"
2020-09-15 17:33:49 +02:00
}
]
}
2020-07-14 18:22:31 +02:00
] ,
2020-09-15 17:33:49 +02:00
"out" : [
{
"x" : 740 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d3caa802.6f22d8" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3a773a31.a6caee" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5d4c755a.800b44" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
}
] ,
"env" : [ ] ,
"color" : "#A6BBCF" ,
"icon" : "node-red-contrib-camerapi/photo.png"
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "714bd4fe.163ab4" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Process metadata" ,
"info" : "" ,
"category" : "" ,
"in" : [
2020-07-14 18:22:31 +02:00
{
2020-09-15 17:33:49 +02:00
"x" : 40 ,
"y" : 80 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "706715a3.5ad1c4"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
"x" : 700 ,
"y" : 80 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "7cdadcd1.736f04" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
}
] ,
"env" : [ ] ,
"color" : "#DDAA99"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "bee3b478.ef4b88" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "MQTT Receive & Plot" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"info" : "# MQTT Topics follows this architecture:\n\n - actuator : This topic adresses the stepper control thread\n No publication under this topic should happen from Python\n - actuator/pump : Control of the pump\n The message is something like \"FORWARD 10 1\"\n to move 10mL forward at 1mL/min\n Receive only\n - actuator/focus : Control of the focus stage\n The message is something like \"UP 10\"\n to move up 10mm\n Receive only\n - imager/image : This topic adresses the imaging thread\n Receive only\n - status : This topics sends feedback to Node-Red\n No publication or receive at this level\n - status/pump : State of the pump\n Is one of Start, Done, Interrupted\n Publish only\n - status/focus : State of the focus stage\n Is one of Start, Done, Interrupted\n Publish only\n - status/imager : State of the imager\n Is one of Start, Completed or 12_11_15_0.1.jpg has been imaged.\n Publish only\n - status/segmentation : Status of the segmentation\n - status/segmentation/name\n - status/segmentation/object_id\n - status/segmentation/metric\n" ,
2020-09-15 17:33:49 +02:00
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#F3B567" ,
"icon" : "node-red/bridge.svg"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9c3e6ad4.7471a8" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "System Commands" ,
"info" : "" ,
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#FFCC66" ,
"icon" : "node-red-dashboard/ui_button.png"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1a447be0.198674" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Object metadata" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 60 ,
"y" : 160 ,
2020-09-15 17:33:49 +02:00
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5cdbcd15.17ec94"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c2ccc2e1.a697f8"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b3e8d04.7c83d3"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
"x" : 1060 ,
"y" : 159 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f435f66d.26d73" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "79026dc4.133a7c" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
2020-07-14 18:22:31 +02:00
} ,
{
2020-09-15 17:33:49 +02:00
"x" : 1060 ,
"y" : 59 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9c08f843.b1e1b" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "157ba5ca.c88a52" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
2020-07-14 18:22:31 +02:00
}
] ,
2020-09-15 17:33:49 +02:00
"env" : [ ] ,
"color" : "#DDAA99"
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "758bc08f.c57318" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Acquisition metadata" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 50 ,
"y" : 30 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f3658d30.b8448"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5acd51d4.4ab13"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "de2c90cf.b73b08"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5e3dec55.881074"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d3ca8847.4d1ae"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1f133196.96564e"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3414b477.4d711c"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a52e7caf.6bde48"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "68fa1227.dbdd5c"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
"x" : 740 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "98d1f331.a06938" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3b9700c4.b93ec" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "42505cbd.f02b1c" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "2f9ae002.b4c96" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c86d98d4.c56538" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "13b51e1e.1f603a" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6c391d10.2f9744" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "163df12e.f73f5f" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
} ,
{
"x" : 900 ,
"y" : 360 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "701120fd.c5516" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
}
] ,
"env" : [ ] ,
"color" : "#DDAA99"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "977131e7.c2e76" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Pump actuation" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 40 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "cc757614.c8fc58"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8ae06f9a.4b253"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
"x" : 700 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b8bf2a9.be099d8" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f1b85f22.ac673" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
}
] ,
"env" : [ ] ,
"color" : "#A6BBCF" ,
"icon" : "font-awesome/fa-recycle"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a0f9bde.423644" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Focus actuation" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 40 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "411211be.745ef8"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 1040 ,
"y" : 40 ,
2020-09-15 17:33:49 +02:00
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b69e435f.b93558" ,
2020-09-15 17:33:49 +02:00
"port" : 0
2020-10-06 17:22:25 +02:00
} ,
{
"id" : "d9930546.489a58" ,
"port" : 0
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"env" : [ ] ,
"color" : "#A6BBCF" ,
"icon" : "node-red/sort.svg"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "81483277.2521e" ,
2020-09-15 17:33:49 +02:00
"type" : "subflow" ,
"name" : "Sample metadata" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 40 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d027a6bf.7049e8"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "45911c98.2bd83c"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5a811caf.0f3144"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1e09a4ab.72996b"
2020-09-15 17:33:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a3272681.f271c8"
2020-09-15 17:33:49 +02:00
}
]
}
] ,
"out" : [
{
"x" : 840 ,
"y" : 40 ,
"wires" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "adaccbb2.320458" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a63c1b66.f9a77" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "67fc8b3f.96c6cc" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8cc6c6f1.65bf28" ,
2020-09-15 17:33:49 +02:00
"port" : 0
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "91a896c8.7c9fb8" ,
2020-09-15 17:33:49 +02:00
"port" : 0
}
]
}
] ,
"env" : [ ] ,
"color" : "#DDAA99"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "4b508eab.dccae8" ,
"type" : "subflow" ,
"name" : "Segmentation control" ,
"info" : "" ,
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#D7D7A0" ,
"icon" : "node-red/db.svg"
} ,
{
"id" : "674362b7.9b6574" ,
"type" : "subflow" ,
"name" : "Camera settings" ,
"info" : "" ,
"category" : "" ,
"in" : [ ] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#3FADB5" ,
"icon" : "font-awesome/fa-camera"
} ,
2020-10-06 17:22:25 +02:00
{
"id" : "d95291dc.83b0b8" ,
"type" : "subflow" ,
"name" : "Python Startup" ,
"info" : "" ,
"category" : "" ,
"in" : [
{
"x" : 160 ,
"y" : 40 ,
"wires" : [
{
"id" : "afa9f4b.2e77988"
} ,
{
"id" : "35ea3cf0.a398ac"
} ,
{
"id" : "a776b9fc.d542e8"
}
]
}
] ,
"out" : [ ] ,
"env" : [ ] ,
"color" : "#DDAA99"
} ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
{
"id" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Monitor RPi" ,
2020-10-06 17:22:25 +02:00
"tab" : "a3de84cd.c01b6" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"order" : 13 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
2020-10-06 17:22:25 +02:00
"width" : "24" ,
2020-09-15 17:33:49 +02:00
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "75a5ce1f.728d" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Acquisition actuation" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 11 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : 24 ,
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "758f41b8.1680c8" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Acquisition inputs" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 10 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : "24" ,
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "eef6f881.7b3b38" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Process metadata" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 9 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : 24 ,
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6d1af0ab.7b4a18" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "MQTT Plots" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 14 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : "24" ,
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ab1d06d6.bf9898" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Object metadata" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-09-15 17:33:49 +02:00
"order" : 2 ,
"disp" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : "24" ,
2020-10-06 17:22:25 +02:00
"collapse" : true
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "4361c3b6.e2b7a4" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Acquisition metadata" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-09-15 17:33:49 +02:00
"order" : 3 ,
"disp" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : "24" ,
2020-10-06 17:22:25 +02:00
"collapse" : true
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "34f03c4a.abdf94" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Pump actuation" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 8 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : "24" ,
"collapse" : false
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "de7c8e82.7faa98" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Focus actuation" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 7 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
"width" : "24" ,
"collapse" : false
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8dc3722c.06efa8" ,
2020-09-15 17:33:49 +02:00
"type" : "mqtt-broker" ,
"z" : "" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
2020-09-15 17:33:49 +02:00
"broker" : "0.0.0.0" ,
"port" : "1883" ,
"clientid" : "Client_node" ,
"usetls" : false ,
"compatmode" : false ,
"keepalive" : "60" ,
"cleansession" : true ,
"birthTopic" : "" ,
"birthQos" : "0" ,
"birthPayload" : "" ,
"closeTopic" : "" ,
"closeQos" : "0" ,
"closePayload" : "" ,
"willTopic" : "" ,
"willQos" : "0" ,
"willPayload" : ""
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "71c63dd4.311c44" ,
2020-07-14 18:27:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
2020-10-06 17:22:25 +02:00
"name" : "Sample Metadata" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-09-15 17:33:49 +02:00
"order" : 1 ,
2020-07-14 18:27:49 +02:00
"disp" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : "24" ,
"collapse" : true
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d10d9d99.00f4b8" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_tab" ,
"z" : "" ,
"name" : "Acquisition" ,
"icon" : "fa-eyedropper" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"order" : 1 ,
2020-09-15 17:33:49 +02:00
"disabled" : false ,
"hidden" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "59434d8d.70ed94" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_group" ,
"z" : "" ,
"name" : "Streaming camera" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 5 ,
2020-09-15 17:33:49 +02:00
"disp" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : "24" ,
2020-09-15 17:33:49 +02:00
"collapse" : false
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9b06d49f.aa144" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_base" ,
"theme" : {
"name" : "theme-dark" ,
"lightTheme" : {
"default" : "#0094CE" ,
"baseColor" : "#0094CE" ,
"baseFont" : "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"edited" : true ,
2020-09-15 17:33:49 +02:00
"reset" : false
} ,
"darkTheme" : {
"default" : "#097479" ,
"baseColor" : "#097479" ,
"baseFont" : "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" ,
"edited" : true ,
"reset" : false
} ,
"customTheme" : {
"name" : "Untitled Theme 1" ,
"default" : "#4B7930" ,
"baseColor" : "#4B7930" ,
"baseFont" : "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
} ,
"themeState" : {
"base-color" : {
"default" : "#097479" ,
"value" : "#097479" ,
"edited" : false
} ,
"page-titlebar-backgroundColor" : {
"value" : "#097479" ,
"edited" : false
} ,
"page-backgroundColor" : {
"value" : "#111111" ,
"edited" : false
} ,
"page-sidebar-backgroundColor" : {
"value" : "#333333" ,
"edited" : false
} ,
"group-textColor" : {
"value" : "#0eb8c0" ,
"edited" : false
} ,
"group-borderColor" : {
"value" : "#555555" ,
"edited" : false
} ,
"group-backgroundColor" : {
"value" : "#333333" ,
"edited" : false
} ,
"widget-textColor" : {
"value" : "#eeeeee" ,
"edited" : false
} ,
"widget-backgroundColor" : {
"value" : "#097479" ,
"edited" : false
} ,
"widget-borderColor" : {
"value" : "#333333" ,
"edited" : false
} ,
"base-font" : {
"value" : "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
}
} ,
"angularTheme" : {
"primary" : "indigo" ,
"accents" : "blue" ,
"warn" : "red" ,
"background" : "grey"
2020-07-14 18:27:49 +02:00
}
2020-09-15 17:33:49 +02:00
} ,
"site" : {
2020-10-06 17:22:25 +02:00
"name" : "PlanktoScope Dashboard" ,
2020-09-15 17:33:49 +02:00
"hideToolbar" : "false" ,
2020-10-06 17:22:25 +02:00
"allowSwipe" : "true" ,
2020-09-15 17:33:49 +02:00
"lockMenu" : "false" ,
"allowTempTheme" : "true" ,
"dateFormat" : "DD/MM/YYYY" ,
"sizes" : {
"sx" : 48 ,
"sy" : 48 ,
"gx" : 6 ,
"gy" : 6 ,
"cx" : 6 ,
"cy" : 6 ,
"px" : 0 ,
"py" : 0
}
}
2020-07-14 18:27:49 +02:00
} ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
{
"id" : "a3de84cd.c01b6" ,
"type" : "ui_tab" ,
"z" : "" ,
"name" : "Management" ,
"icon" : "dashboard" ,
"order" : 2 ,
"disabled" : false ,
"hidden" : false
} ,
{
"id" : "adcd0ef7.81a7f8" ,
"type" : "ui_group" ,
"z" : "" ,
"name" : "RPi commands" ,
"tab" : "a3de84cd.c01b6" ,
"order" : 1 ,
"disp" : true ,
2020-10-06 17:22:25 +02:00
"width" : 13 ,
"collapse" : false
} ,
{
"id" : "566dcd6a.03db74" ,
"type" : "ui_group" ,
"z" : "" ,
"name" : "Segmentation control" ,
"tab" : "d10d9d99.00f4b8" ,
"order" : 12 ,
"disp" : true ,
"width" : "24" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"collapse" : false
} ,
{
2020-10-06 17:22:25 +02:00
"id" : "e8b67968.dea6" ,
"type" : "ui_group" ,
"z" : "" ,
"name" : "Camera settings" ,
"tab" : "d10d9d99.00f4b8" ,
"order" : 6 ,
"disp" : true ,
"width" : "24" ,
"collapse" : true
} ,
{
"id" : "f1dc35d9.99b9f8" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"type" : "ui_spacer" ,
"name" : "spacer" ,
"group" : "adcd0ef7.81a7f8" ,
"order" : 2 ,
2020-10-06 17:22:25 +02:00
"width" : 13 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"height" : 1
} ,
{
2020-10-06 17:22:25 +02:00
"id" : "248136a7.29b74a" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"type" : "ui_spacer" ,
"name" : "spacer" ,
"group" : "adcd0ef7.81a7f8" ,
"order" : 4 ,
"width" : 5 ,
"height" : 1
} ,
{
2020-10-06 17:22:25 +02:00
"id" : "7b7849e8.363288" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"type" : "ui_group" ,
2020-10-06 17:22:25 +02:00
"z" : "1a447be0.198674" ,
"name" : "GPS" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 4 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"disp" : true ,
"width" : "24" ,
"collapse" : false
} ,
{
2020-10-06 17:22:25 +02:00
"id" : "91acd434.6205" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"type" : "ui_group" ,
2020-10-06 17:22:25 +02:00
"z" : "bee3b478.ef4b88" ,
"name" : "Status" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"tab" : "d10d9d99.00f4b8" ,
2020-10-06 17:22:25 +02:00
"order" : 13 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"disp" : true ,
"width" : "24" ,
2020-10-06 17:22:25 +02:00
"collapse" : true
} ,
{
"id" : "4e3f24b.177a7dc" ,
"type" : "ui_spacer" ,
"name" : "spacer" ,
"group" : "de7c8e82.7faa98" ,
"order" : 7 ,
"width" : 6 ,
"height" : 1
} ,
{
"id" : "4bb924fe.fc097c" ,
"type" : "ui_spacer" ,
"name" : "spacer" ,
"group" : "de7c8e82.7faa98" ,
"order" : 9 ,
"width" : 10 ,
"height" : 1
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
} ,
{
"id" : "98b8d88c.dc5d" ,
2020-07-14 18:22:31 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"command" : "free -m | grep \"Mem\" | awk -F ' ' '{print $3}'" ,
2020-07-14 18:22:31 +02:00
"addpay" : false ,
"append" : "" ,
2020-09-15 17:33:49 +02:00
"useSpawn" : "" ,
2020-07-14 18:22:31 +02:00
"timer" : "" ,
2020-09-15 17:33:49 +02:00
"name" : "Get memory used" ,
"x" : 430 ,
"y" : 100 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"ddf0e242.88258" ,
"f1a7a389.2cc528"
2020-07-14 18:22:31 +02:00
] ,
2020-09-15 17:33:49 +02:00
[ ] ,
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "34130a77.042d46" ,
2020-09-15 17:33:49 +02:00
"type" : "inject" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"repeat" : "1" ,
"crontab" : "" ,
"once" : false ,
"onceDelay" : "" ,
"topic" : "" ,
"payload" : "" ,
"payloadType" : "num" ,
"x" : 210 ,
"y" : 100 ,
"wires" : [
2020-07-14 18:22:31 +02:00
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"98b8d88c.dc5d"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ddf0e242.88258" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Memory Load Chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 8 ,
"width" : 19 ,
"height" : 4 ,
"label" : "Memory Load Chart" ,
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "bezier" ,
"nodata" : "" ,
"dot" : true ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "20" ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "60" ,
"cutout" : 0 ,
"useOneColor" : false ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : false ,
"outputs" : 1 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 650 ,
2020-09-15 17:33:49 +02:00
"y" : 120 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f1a7a389.2cc528" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_gauge" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Memory Load Donut" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 7 ,
"width" : 5 ,
"height" : 4 ,
"gtype" : "donut" ,
"title" : "Memory Load Donut" ,
"label" : "Mo" ,
"format" : "{{value}}" ,
"min" : 0 ,
"max" : "4000" ,
"colors" : [
"#00b500" ,
"#e6e600" ,
"#ca3838"
] ,
"seg1" : "1000" ,
"seg2" : "2000" ,
"x" : 660 ,
"y" : 80 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "30fcb8f6.12fe" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_gauge" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "CPU Temp Donut" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 1 ,
"width" : 5 ,
"height" : 4 ,
"gtype" : "donut" ,
"title" : "CPU Temp Donut" ,
"label" : "C" ,
"format" : "{{value}}" ,
"min" : "35" ,
"max" : "55" ,
"colors" : [
"#00b500" ,
"#e6e600" ,
"#ca3838"
] ,
"seg1" : "" ,
"seg2" : "" ,
"x" : 650 ,
"y" : 160 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "81105630.ed06e8" ,
2020-07-14 18:22:31 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"command" : "vcgencmd measure_temp | tr -d \"temp=\" | tr -d \"'C\" | tr -d \"\\n\"" ,
2020-07-14 18:22:31 +02:00
"addpay" : false ,
"append" : "" ,
2020-09-15 17:33:49 +02:00
"useSpawn" : "" ,
2020-07-14 18:22:31 +02:00
"timer" : "" ,
2020-09-15 17:33:49 +02:00
"name" : "RPi Temp." ,
"x" : 410 ,
"y" : 180 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"59fe3900.da6c8" ,
"30fcb8f6.12fe" ,
"d70d3e88.eaca48"
2020-07-14 18:22:31 +02:00
] ,
[ ] ,
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d70d3e88.eaca48" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "CPU Temp Chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 2 ,
"width" : 19 ,
"height" : 4 ,
"label" : "CPU Temp Chart" ,
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "20" ,
"removeOlderPoints" : "200" ,
"removeOlderUnit" : "60" ,
"cutout" : 0 ,
"useOneColor" : false ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : true ,
"outputs" : 1 ,
"x" : 650 ,
"y" : 200 ,
"wires" : [
[ ]
2020-07-14 18:22:31 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6e383122.133d5" ,
2020-09-15 17:33:49 +02:00
"type" : "python3-function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "fan.py" ,
"func" : "#!/usr/bin/python\nimport smbus\nimport sys\n\nstate = msg[\"payload\"]\n\nbus = smbus.SMBus(1)\n\nDEVICE_ADDRESS = 0x0d\n\nif state == \"off\":\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\nif state == \"on\":\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)" ,
"outputs" : 1 ,
"x" : 1290 ,
"y" : 140 ,
2020-01-08 14:32:46 +01:00
"wires" : [
2020-09-15 17:33:49 +02:00
[ ]
2020-01-08 14:32:46 +01:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "59fe3900.da6c8" ,
2020-09-15 17:33:49 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-01-08 14:32:46 +01:00
"name" : "" ,
2020-09-15 17:33:49 +02:00
"property" : "payload" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "gt" ,
"v" : "45" ,
"vt" : "num"
} ,
{
"t" : "lte" ,
2020-10-06 17:22:25 +02:00
"v" : "35" ,
2020-09-15 17:33:49 +02:00
"vt" : "num"
}
] ,
"checkall" : "true" ,
"repair" : false ,
"outputs" : 2 ,
"x" : 950 ,
2020-07-14 18:22:31 +02:00
"y" : 140 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"1d11bfc1.ad4788"
2020-09-15 17:33:49 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"5aeccc80.5e9c54"
2020-01-08 14:32:46 +01:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5aeccc80.5e9c54" ,
2020-09-15 17:33:49 +02:00
"type" : "change" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-07-14 18:27:49 +02:00
"name" : "" ,
2020-09-15 17:33:49 +02:00
"rules" : [
{
"t" : "set" ,
"p" : "payload" ,
"pt" : "msg" ,
"to" : "off" ,
"tot" : "str"
}
] ,
"action" : "" ,
"property" : "" ,
"from" : "" ,
"to" : "" ,
"reg" : false ,
"x" : 1120 ,
"y" : 160 ,
2020-07-14 18:27:49 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6e383122.133d5"
2020-07-14 18:27:49 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8338294b.8082d" ,
2020-09-15 17:33:49 +02:00
"type" : "inject" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"repeat" : "5" ,
"crontab" : "" ,
"once" : false ,
"onceDelay" : "" ,
"topic" : "" ,
"payload" : "" ,
"payloadType" : "date" ,
"x" : 190 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 260 ,
2020-07-14 18:27:49 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"e7fe62ae.efb4f" ,
"eba0a98a.e4d56" ,
"81105630.ed06e8"
2020-07-14 18:27:49 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "e7fe62ae.efb4f" ,
2020-07-14 18:27:49 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"command" : "top -d 0.5 -b -n2 | grep \"Cpu(s)\"|tail -n 1 | awk '{print $2 + $4}' | tr -d \"\\n\"" ,
2020-07-14 18:27:49 +02:00
"addpay" : false ,
"append" : "" ,
2020-09-15 17:33:49 +02:00
"useSpawn" : "" ,
2020-07-14 18:27:49 +02:00
"timer" : "" ,
2020-09-15 17:33:49 +02:00
"name" : "CPU Load" ,
"x" : 410 ,
"y" : 260 ,
2020-07-14 18:27:49 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"aa4065d2.14a66" ,
"a9aef217.f0aae"
2020-07-14 18:27:49 +02:00
] ,
[ ] ,
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "eba0a98a.e4d56" ,
2020-07-14 18:27:49 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"command" : "free | grep Mem | awk '{print 100*($4+$6+$7)/$2}' | awk -F \".\" '{print $1}' | tr -d \"\\n\"" ,
"addpay" : false ,
2020-07-14 18:27:49 +02:00
"append" : "" ,
2020-09-15 17:33:49 +02:00
"useSpawn" : "" ,
2020-07-14 18:27:49 +02:00
"timer" : "" ,
2020-09-15 17:33:49 +02:00
"name" : "Free Memory" ,
"x" : 410 ,
"y" : 340 ,
2020-07-14 18:27:49 +02:00
"wires" : [
2020-09-15 17:33:49 +02:00
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"539c69d4.618bd8" ,
"96ceb8d7.0ed66"
2020-09-15 17:33:49 +02:00
] ,
2020-07-14 18:27:49 +02:00
[ ] ,
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "aa4065d2.14a66" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_gauge" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "CPU Load Donut" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 5 ,
"width" : 5 ,
"height" : 4 ,
"gtype" : "donut" ,
"title" : "CPU Load Donut" ,
"label" : "CPU" ,
"format" : "{{value}}" ,
"min" : 0 ,
"max" : "100" ,
"colors" : [
"#00b500" ,
"#e6e600" ,
"#ca3838"
] ,
"seg1" : "" ,
"seg2" : "" ,
"x" : 650 ,
"y" : 240 ,
"wires" : [ ]
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "539c69d4.618bd8" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_gauge" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Free memory Donut" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 9 ,
"width" : 5 ,
"height" : 4 ,
"gtype" : "donut" ,
"title" : "Free memory Donut" ,
"label" : "RAM" ,
"format" : "{{value}}" ,
"min" : 0 ,
"max" : "200" ,
"colors" : [
"#00b500" ,
"#e6e600" ,
"#ca3838"
2020-07-14 18:27:49 +02:00
] ,
2020-09-15 17:33:49 +02:00
"seg1" : "" ,
"seg2" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 650 ,
2020-09-15 17:33:49 +02:00
"y" : 320 ,
"wires" : [ ]
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9031b9ea.483fa8" ,
2020-07-14 18:22:31 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"command" : "df -h | grep /dev/root | awk -F ' ' '{print $3}' | tr -d G | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \" " ,
"addpay" : false ,
2020-07-14 18:22:31 +02:00
"append" : "" ,
2020-09-15 17:33:49 +02:00
"useSpawn" : "" ,
2020-07-14 18:22:31 +02:00
"timer" : "" ,
2020-09-15 17:33:49 +02:00
"name" : "Disk Usage" ,
"x" : 410 ,
"y" : 420 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"32eded3f.f3b42a" ,
"49c71440.02a25c"
2020-09-15 17:33:49 +02:00
] ,
[ ] ,
2020-07-14 18:22:31 +02:00
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "32eded3f.f3b42a" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_gauge" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Disk Usage Donut" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-07-14 18:22:31 +02:00
"order" : 3 ,
2020-09-15 17:33:49 +02:00
"width" : 5 ,
"height" : 4 ,
"gtype" : "donut" ,
"title" : "Disk Usage Donut" ,
"label" : "Go" ,
2020-07-14 18:22:31 +02:00
"format" : "{{value}}" ,
2020-09-15 17:33:49 +02:00
"min" : 0 ,
"max" : "256" ,
"colors" : [
"#00b500" ,
"#e6e600" ,
"#ca3838"
] ,
"seg1" : "" ,
"seg2" : "" ,
2020-07-14 18:22:31 +02:00
"x" : 650 ,
2020-09-15 17:33:49 +02:00
"y" : 400 ,
"wires" : [ ]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a9aef217.f0aae" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "CPU Load Chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 6 ,
"width" : 19 ,
"height" : 4 ,
"label" : "CPU Load Chart" ,
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "20" ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "60" ,
"cutout" : 0 ,
"useOneColor" : false ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : true ,
"outputs" : 1 ,
2020-07-14 18:22:31 +02:00
"x" : 640 ,
2020-09-15 17:33:49 +02:00
"y" : 280 ,
2020-07-14 18:22:31 +02:00
"wires" : [
2020-09-15 17:33:49 +02:00
[ ]
2020-07-14 18:22:31 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "96ceb8d7.0ed66" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Free memory Chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 10 ,
"width" : 19 ,
"height" : 4 ,
"label" : "Free memory Chart" ,
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "20" ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "60" ,
"cutout" : 0 ,
"useOneColor" : false ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : true ,
"outputs" : 1 ,
"x" : 650 ,
"y" : 360 ,
2020-07-14 18:22:31 +02:00
"wires" : [
2020-09-15 17:33:49 +02:00
[ ]
2020-07-14 18:22:31 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "fb614565.7a2108" ,
2020-09-15 17:33:49 +02:00
"type" : "inject" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"repeat" : "60" ,
"crontab" : "" ,
"once" : false ,
"onceDelay" : "" ,
"topic" : "" ,
"payload" : "" ,
"payloadType" : "date" ,
"x" : 190 ,
"y" : 420 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"9031b9ea.483fa8"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "49c71440.02a25c" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "Disk Usage Chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "779606c9.19d2b8" ,
2020-09-15 17:33:49 +02:00
"order" : 4 ,
"width" : 19 ,
"height" : 4 ,
"label" : "Disk Usage Chart" ,
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "20" ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "60" ,
"cutout" : 0 ,
"useOneColor" : false ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : true ,
"outputs" : 1 ,
2020-07-14 18:22:31 +02:00
"x" : 650 ,
2020-09-15 17:33:49 +02:00
"y" : 440 ,
2020-07-14 18:22:31 +02:00
"wires" : [
2020-09-15 17:33:49 +02:00
[ ]
2020-07-14 18:22:31 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1d11bfc1.ad4788" ,
2020-09-15 17:33:49 +02:00
"type" : "change" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "21b3da63.2cef2e" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"rules" : [
{
"t" : "set" ,
"p" : "payload" ,
"pt" : "msg" ,
"to" : "on" ,
"tot" : "str"
}
] ,
"action" : "" ,
"property" : "" ,
"from" : "" ,
"to" : "" ,
"reg" : false ,
"x" : 1120 ,
"y" : 120 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6e383122.133d5"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "4b489713.ccde5" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "75a5ce1f.728d" ,
2020-10-06 17:22:25 +02:00
"order" : 1 ,
2020-09-15 17:33:49 +02:00
"width" : 16 ,
2020-07-14 18:22:31 +02:00
"height" : 1 ,
2020-01-08 14:32:46 +01:00
"passthru" : false ,
2020-09-15 17:33:49 +02:00
"label" : "Start Acquisition" ,
2020-01-08 14:32:46 +01:00
"tooltip" : "" ,
2020-09-15 17:33:49 +02:00
"color" : "" ,
"bgcolor" : "" ,
2020-01-08 14:32:46 +01:00
"icon" : "" ,
"payload" : "" ,
"payloadType" : "str" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"topic" : "imager/image" ,
2020-09-15 17:33:49 +02:00
"x" : 200 ,
"y" : 100 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[
2020-10-06 17:22:25 +02:00
"52ea7d01.711034" ,
"40c12463.a1f84c"
2020-01-08 14:32:46 +01:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c9f510c0.7d1328" ,
2020-01-08 14:32:46 +01:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-09-15 17:33:49 +02:00
"name" : "image.js" ,
2020-10-06 17:22:25 +02:00
"func" : "state = global.get(\"state\");\nglobal.set('img_counter',0);\nglobal.set('obj_counter',0);\nif (state === null){state=\"free\"}\n\nvar sleep_before= global.get(\"custom_sleep_before\");\nvar nb_step= global.get(\"custom_nb_step\");\nvar nb_frame= global.get(\"custom_nb_frame\");\n\nif (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Duration before the acquisition\";\n \n}else if (nb_step === undefined || nb_step === \"\" || nb_step === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of step in between two frames\";\n \n}else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n \n}else {\n msg.payload={\"action\":\"image\", \n \"sleep\":sleep_before,\n \"volume\":nb_step,\n \"nb_frame\":nb_frame,\n }\n}\n\nreturn msg;" ,
2020-01-08 14:32:46 +01:00
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 560 ,
2020-09-15 17:33:49 +02:00
"y" : 100 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"d6ebaa2.ea21d58"
2020-01-08 14:32:46 +01:00
]
2020-09-15 17:33:49 +02:00
] ,
"info" : "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktonScope/scripts/focus.py 650 up\n"
2020-01-08 14:32:46 +01:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d6ebaa2.ea21d58" ,
2020-09-15 17:33:49 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"property" : "topic" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "imager/image" ,
2020-09-15 17:33:49 +02:00
"vt" : "str"
} ,
{
"t" : "eq" ,
"v" : "Missing entry :" ,
"vt" : "str"
}
] ,
"checkall" : "true" ,
"repair" : false ,
"outputs" : 2 ,
2020-10-06 17:22:25 +02:00
"x" : 710 ,
2020-09-15 17:33:49 +02:00
"y" : 100 ,
2020-01-08 14:32:46 +01:00
"wires" : [
2020-09-15 17:33:49 +02:00
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"c3e50240.82aa58"
2020-09-15 17:33:49 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"20e0a8c8.edbeb"
2020-09-15 17:33:49 +02:00
]
2020-01-08 14:32:46 +01:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "20e0a8c8.edbeb" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_toast" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-09-15 17:33:49 +02:00
"position" : "dialog" ,
"displayTime" : "3" ,
"highlight" : "" ,
"sendall" : true ,
2020-01-08 14:32:46 +01:00
"outputs" : 1 ,
2020-09-15 17:33:49 +02:00
"ok" : "OK" ,
"cancel" : "" ,
"raw" : false ,
"topic" : "" ,
"name" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 870 ,
"y" : 140 ,
2020-01-08 14:32:46 +01:00
"wires" : [
2020-09-15 17:33:49 +02:00
[ ]
2020-01-08 14:32:46 +01:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c3e50240.82aa58" ,
2020-09-15 17:33:49 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-01-08 14:32:46 +01:00
"name" : "" ,
2020-09-15 17:33:49 +02:00
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
2020-10-06 17:22:25 +02:00
"x" : 850 ,
"y" : 60 ,
2020-09-15 17:33:49 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3a4450b1.4459a8" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-09-15 17:33:49 +02:00
"name" : "Stop Acquisition" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "75a5ce1f.728d" ,
2020-10-06 17:22:25 +02:00
"order" : 2 ,
2020-09-15 17:33:49 +02:00
"width" : 8 ,
"height" : 1 ,
"passthru" : true ,
"label" : "STOP ACQUISITION" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"payload" : "{\"action\":\"stop\"}" ,
"payloadType" : "json" ,
"topic" : "imager/image" ,
2020-09-15 17:33:49 +02:00
"x" : 200 ,
"y" : 140 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"d74210ef.edc15"
2020-01-08 14:32:46 +01:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d74210ef.edc15" ,
2020-09-15 17:33:49 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "130e0533.4f1813" ,
2020-01-08 14:32:46 +01:00
"name" : "" ,
2020-09-15 17:33:49 +02:00
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
"x" : 390 ,
2020-09-15 17:33:49 +02:00
"y" : 140 ,
"wires" : [ ]
} ,
2020-01-08 14:32:46 +01:00
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d3caa802.6f22d8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "custom_nb_step" ,
2020-10-06 17:22:25 +02:00
"label" : "Volume in mL between two images" ,
"tooltip" : "TODO This should be in mm ?" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "758f41b8.1680c8" ,
2020-07-14 18:22:31 +02:00
"order" : 2 ,
2020-01-08 14:32:46 +01:00
"width" : 0 ,
"height" : 0 ,
2020-07-14 18:22:31 +02:00
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "custom_nb_step" ,
"x" : 540 ,
"y" : 80 ,
2020-01-08 14:32:46 +01:00
"wires" : [
2020-07-14 18:22:31 +02:00
[ ]
2020-01-08 14:32:46 +01:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5d4c755a.800b44" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "custom_nb_frame" ,
"label" : "Number of images per acquisition" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "758f41b8.1680c8" ,
2020-07-14 18:22:31 +02:00
"order" : 3 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "custom_nb_frame" ,
"x" : 530 ,
"y" : 120 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8887f3e7.e79b5" ,
2020-01-08 14:32:46 +01:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "get custom_nb_step" ,
"func" : "msg.payload = msg.payload.custom_nb_step;\nreturn msg;" ,
2020-01-08 14:32:46 +01:00
"outputs" : 1 ,
"noerr" : 0 ,
2020-10-06 17:22:25 +02:00
"initialize" : "" ,
"finalize" : "" ,
2020-01-08 14:32:46 +01:00
"x" : 220 ,
2020-07-14 18:22:31 +02:00
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"d3caa802.6f22d8"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "600c2b46.83db14" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "get custom_nb_frame" ,
"func" : "msg.payload = msg.payload.custom_nb_frame;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 220 ,
"y" : 120 ,
2020-01-08 14:32:46 +01:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"5d4c755a.800b44"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "14be4afa.2ba67d" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "get custom_sleep_before" ,
"func" : "msg.payload = msg.payload.custom_sleep_before;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 230 ,
"y" : 40 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"3a773a31.a6caee"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3a773a31.a6caee" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1bc3f9f9.1ee996" ,
2020-07-14 18:22:31 +02:00
"name" : "custom_sleep_before" ,
"label" : "Duration before the acquisition (s)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "758f41b8.1680c8" ,
2020-07-14 18:22:31 +02:00
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "custom_sleep_before" ,
"x" : 520 ,
"y" : 40 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "7cdadcd1.736f04" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "714bd4fe.163ab4" ,
2020-07-14 18:22:31 +02:00
"name" : "process_id" ,
"label" : "Id of the process" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "eef6f881.7b3b38" ,
2020-07-14 18:22:31 +02:00
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "process_id" ,
"x" : 550 ,
"y" : 80 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "706715a3.5ad1c4" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "714bd4fe.163ab4" ,
2020-07-14 18:22:31 +02:00
"name" : "get process_id" ,
"func" : "msg.payload = msg.payload.process_id+1;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 200 ,
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"7cdadcd1.736f04"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8cb80d95.13d2e8" ,
2020-07-14 18:22:31 +02:00
"type" : "mqtt in" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"topic" : "status/#" ,
2020-07-14 18:22:31 +02:00
"qos" : "0" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"datatype" : "json" ,
"broker" : "8dc3722c.06efa8" ,
"x" : 70 ,
"y" : 300 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
2020-10-06 17:22:25 +02:00
"2aa5b118.d75f2e" ,
"f6fd015e.5c1fe"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ecedbda4.fed15" ,
2020-07-14 18:22:31 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
"name" : "topic filter" ,
2020-07-14 18:22:31 +02:00
"property" : "topic" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/pump" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
} ,
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/focus" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
} ,
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/imager" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
} ,
{
"t" : "cont" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/segmenter" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
}
] ,
"checkall" : "true" ,
"repair" : false ,
"outputs" : 4 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 360 ,
"y" : 300 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
2020-10-06 17:22:25 +02:00
"117aad13.53e11b" ,
"d700c8a1.2d1f48"
2020-07-14 18:22:31 +02:00
] ,
[
2020-10-06 17:22:25 +02:00
"117aad13.53e11b" ,
"dc72e121.0aacd"
2020-07-14 18:22:31 +02:00
] ,
[
2020-10-06 17:22:25 +02:00
"af9a1d81.c21fa8" ,
"5a159d39.3bdca4"
2020-07-14 18:22:31 +02:00
] ,
[
2020-10-06 17:22:25 +02:00
"30a9de16.d55cda" ,
"89058790.909e7"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "af9a1d81.c21fa8" ,
2020-07-14 18:22:31 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
"name" : "Imaging state" ,
2020-07-14 18:22:31 +02:00
"property" : "payload" ,
"propertyType" : "msg" ,
"rules" : [
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"t" : "else"
2020-07-14 18:22:31 +02:00
} ,
{
2020-10-06 17:22:25 +02:00
"t" : "jsonata_exp" ,
"v" : "$contains(msg.payload.status, \"jpg\")\t" ,
"vt" : "jsonata"
2020-07-14 18:22:31 +02:00
}
] ,
"checkall" : "true" ,
"repair" : false ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"outputs" : 2 ,
2020-10-06 17:22:25 +02:00
"x" : 640 ,
"y" : 340 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"117aad13.53e11b"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"a636cac5.e28448"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a636cac5.e28448" ,
"type" : "function" ,
"z" : "bee3b478.ef4b88" ,
"name" : "img_counter.js" ,
"func" : "img_counter=global.get('img_counter')\nimg_counter=img_counter+1\nglobal.set('img_counter',img_counter)\nmsg.payload = img_counter\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
2020-10-06 17:22:25 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 900 ,
"y" : 400 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"abd84e73.aefc9"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f71d0cda.0a4f88" ,
"type" : "function" ,
"z" : "bee3b478.ef4b88" ,
"name" : "obj_counter.js" ,
"func" : "obj_counter=global.get('obj_counter')\nobj_counter=obj_counter+1\nglobal.set('obj_counter',obj_counter)\nmsg.payload = obj_counter\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
2020-07-14 18:22:31 +02:00
"x" : 900 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 500 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"d0d14f00.e2ff88"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "abd84e73.aefc9" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-07-14 18:22:31 +02:00
"name" : "img_counter" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "6d1af0ab.7b4a18" ,
2020-09-15 17:33:49 +02:00
"order" : 1 ,
"width" : 24 ,
2020-07-14 18:22:31 +02:00
"height" : 2 ,
2020-10-06 17:22:25 +02:00
"label" : "image counter" ,
2020-07-14 18:22:31 +02:00
"chartType" : "horizontalBar" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : 1 ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "3600" ,
"cutout" : 0 ,
"useOneColor" : false ,
2020-10-06 17:22:25 +02:00
"useUTC" : false ,
2020-07-14 18:22:31 +02:00
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : false ,
"outputs" : 1 ,
2020-10-06 17:22:25 +02:00
"x" : 1370 ,
"y" : 400 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "30a9de16.d55cda" ,
2020-07-14 18:22:31 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
"name" : "Segmenter" ,
2020-07-14 18:22:31 +02:00
"property" : "topic" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/segmenter" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
} ,
2020-09-15 17:33:49 +02:00
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/segmenter/name" ,
2020-09-15 17:33:49 +02:00
"vt" : "str"
} ,
2020-07-14 18:22:31 +02:00
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/segmenter/object_id" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
} ,
{
"t" : "eq" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"v" : "status/segmenter/metric" ,
2020-07-14 18:22:31 +02:00
"vt" : "str"
}
] ,
"checkall" : "true" ,
"repair" : false ,
2020-09-15 17:33:49 +02:00
"outputs" : 4 ,
2020-10-06 17:22:25 +02:00
"x" : 630 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 480 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"117aad13.53e11b"
2020-09-15 17:33:49 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"c2d35803.b5024"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"f71d0cda.0a4f88"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"87d402c5.c02008"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d0d14f00.e2ff88" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-07-14 18:22:31 +02:00
"name" : "obj_counter" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "6d1af0ab.7b4a18" ,
2020-09-15 17:33:49 +02:00
"order" : 2 ,
"width" : 24 ,
2020-07-14 18:22:31 +02:00
"height" : 2 ,
"label" : "obj_counter" ,
"chartType" : "horizontalBar" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : false ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : 1 ,
"removeOlderPoints" : "" ,
"removeOlderUnit" : "3600" ,
"cutout" : 0 ,
"useOneColor" : true ,
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : false ,
"outputs" : 1 ,
2020-10-06 17:22:25 +02:00
"x" : 1370 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 500 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d7944cf2.1ddb18" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-09-15 17:33:49 +02:00
"name" : "ex : area" ,
2020-07-14 18:22:31 +02:00
"func" : "msg.payload=msg.payload.object_area\nmsg.topic=\"area\"\n\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
2020-10-06 17:22:25 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 1000 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 540 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
2020-10-06 17:22:25 +02:00
"6f64625f.243fd4" ,
"f6fd015e.5c1fe"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "87d402c5.c02008" ,
2020-07-14 18:22:31 +02:00
"type" : "json" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"property" : "payload" ,
"action" : "" ,
"pretty" : false ,
2020-10-06 17:22:25 +02:00
"x" : 870 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 540 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"d7944cf2.1ddb18"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1403e1a4.528926" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_toast" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-09-15 17:33:49 +02:00
"position" : "top right" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"displayTime" : "5" ,
2020-09-15 17:33:49 +02:00
"highlight" : "" ,
"sendall" : true ,
"outputs" : 0 ,
"ok" : "OK" ,
"cancel" : "" ,
"raw" : false ,
2020-07-14 18:22:31 +02:00
"topic" : "" ,
"name" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 1390 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 280 ,
2020-09-15 17:33:49 +02:00
"wires" : [ ]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6f64625f.243fd4" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_chart" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
2020-09-15 17:33:49 +02:00
"name" : "chart area" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "6d1af0ab.7b4a18" ,
2020-09-15 17:33:49 +02:00
"order" : 3 ,
"width" : 24 ,
"height" : 7 ,
"label" : "chart area" ,
2020-07-14 18:22:31 +02:00
"chartType" : "line" ,
"legend" : "false" ,
"xformat" : "HH:mm:ss" ,
"interpolate" : "linear" ,
"nodata" : "" ,
"dot" : true ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : 1 ,
"removeOlderPoints" : "1000" ,
"removeOlderUnit" : "3600" ,
"cutout" : 0 ,
"useOneColor" : false ,
2020-10-06 17:22:25 +02:00
"useUTC" : false ,
2020-07-14 18:22:31 +02:00
"colors" : [
"#1f77b4" ,
"#aec7e8" ,
"#ff7f0e" ,
"#2ca02c" ,
"#98df8a" ,
"#d62728" ,
"#ff9896" ,
"#9467bd" ,
"#c5b0d5"
] ,
"useOldStyle" : false ,
"outputs" : 1 ,
2020-10-06 17:22:25 +02:00
"x" : 1370 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 540 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c2d35803.b5024" ,
2020-07-14 18:27:49 +02:00
"type" : "debug" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "bee3b478.ef4b88" ,
"name" : "segmentation name" ,
2020-07-14 18:27:49 +02:00
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "true" ,
"targetType" : "full" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"statusVal" : "" ,
"statusType" : "auto" ,
2020-10-06 17:22:25 +02:00
"x" : 920 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 460 ,
2020-07-14 18:27:49 +02:00
"wires" : [ ]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ce12cb65.115838" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "9c3e6ad4.7471a8" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "adcd0ef7.81a7f8" ,
"order" : 3 ,
2020-10-06 17:22:25 +02:00
"width" : 4 ,
2020-09-15 17:33:49 +02:00
"height" : 1 ,
2020-07-14 18:22:31 +02:00
"passthru" : false ,
"label" : "Reboot" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
2020-10-06 17:22:25 +02:00
"payload" : "reboot" ,
2020-07-14 18:22:31 +02:00
"payloadType" : "str" ,
"topic" : "reboot" ,
2020-09-15 17:33:49 +02:00
"x" : 240 ,
2020-07-14 18:22:31 +02:00
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"677f762b.43c648"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "690ed112.f50c3" ,
2020-07-14 18:22:31 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "9c3e6ad4.7471a8" ,
2020-07-14 18:22:31 +02:00
"command" : "sudo" ,
"addpay" : true ,
2020-10-06 17:22:25 +02:00
"append" : "now" ,
2020-07-14 18:22:31 +02:00
"useSpawn" : "false" ,
"timer" : "2" ,
"oldrc" : false ,
"name" : "cmd" ,
"x" : 530 ,
"y" : 80 ,
"wires" : [
[ ] ,
[ ] ,
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "4a608a65.1882ec" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "9c3e6ad4.7471a8" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "adcd0ef7.81a7f8" ,
"order" : 5 ,
2020-10-06 17:22:25 +02:00
"width" : 4 ,
2020-09-15 17:33:49 +02:00
"height" : 1 ,
2020-07-14 18:22:31 +02:00
"passthru" : false ,
"label" : "Shutdown" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
2020-10-06 17:22:25 +02:00
"payload" : "shutdown" ,
2020-07-14 18:22:31 +02:00
"payloadType" : "str" ,
"topic" : "shutdown" ,
2020-10-06 17:22:25 +02:00
"x" : 230 ,
"y" : 160 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"677f762b.43c648"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "677f762b.43c648" ,
2020-07-14 18:22:31 +02:00
"type" : "python3-function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "9c3e6ad4.7471a8" ,
2020-07-14 18:22:31 +02:00
"name" : "action" ,
2020-10-06 17:22:25 +02:00
"func" : "#!/usr/bin/python\nimport smbus\nimport time\nbus = smbus.SMBus(1)\ntime.sleep(1)\n#turn off fan RGB\nbus.write_byte_data(0x0d, 0x07, 0x00)\nbus.write_byte_data(0x0d, 0x07, 0x00)\n\n#msg[\"payload\"] = str(msg[\"topic\"])+' now'\nreturn msg" ,
2020-07-14 18:22:31 +02:00
"outputs" : 1 ,
"x" : 390 ,
2020-10-06 17:22:25 +02:00
"y" : 120 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"50d1becd.7b5f" ,
"690ed112.f50c3"
2020-07-14 18:22:31 +02:00
]
2020-09-15 17:33:49 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "50d1becd.7b5f" ,
2020-09-15 17:33:49 +02:00
"type" : "exec" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "9c3e6ad4.7471a8" ,
2020-09-15 17:33:49 +02:00
"command" : "i2cdetect -y 1" ,
"addpay" : false ,
"append" : "" ,
"useSpawn" : "false" ,
"timer" : "1" ,
"oldrc" : false ,
"name" : "i2c update" ,
"x" : 550 ,
2020-10-06 17:22:25 +02:00
"y" : 160 ,
2020-09-15 17:33:49 +02:00
"wires" : [
[ ] ,
[ ] ,
[ ]
]
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f435f66d.26d73" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "object_depth_min" ,
"label" : "Minimum depth (m)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "ab1d06d6.bf9898" ,
2020-07-14 18:22:31 +02:00
"order" : 3 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "object_depth_min" ,
"format" : "{{value}}" ,
"min" : "0" ,
"max" : "2000" ,
"step" : "1" ,
"x" : 610 ,
"y" : 120 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "79026dc4.133a7c" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "object_depth_max" ,
"label" : "Maximum depth (m)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "ab1d06d6.bf9898" ,
2020-07-14 18:22:31 +02:00
"order" : 2 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "object_depth_max" ,
"format" : "{{value}}" ,
"min" : "0" ,
"max" : "2000" ,
"step" : "1" ,
"x" : 610 ,
"y" : 160 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5cdbcd15.17ec94" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "get object_depth_min" ,
"func" : "msg.payload = msg.payload.object_depth_min;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 360 ,
2020-07-14 18:22:31 +02:00
"y" : 120 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"f435f66d.26d73"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c2ccc2e1.a697f8" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "get object_depth_max" ,
"func" : "msg.payload = msg.payload.object_depth_max;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 360 ,
2020-07-14 18:22:31 +02:00
"y" : 160 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"79026dc4.133a7c"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "cb77803f.357f88" ,
2020-07-14 18:22:31 +02:00
"type" : "gpsd" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"hostname" : "localhost" ,
"port" : "2947" ,
"tpv" : true ,
"sky" : false ,
"info" : false ,
"device" : false ,
"gst" : false ,
"att" : false ,
"x" : 90 ,
"y" : 220 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"b3e8d04.7c83d3" ,
"3f718ceb.5e9f34" ,
"74554b33.14ab6c"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f7ae988c.184598" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_worldmap" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"d" : true ,
2020-10-06 17:22:25 +02:00
"group" : "7b7849e8.363288" ,
2020-07-14 18:22:31 +02:00
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"lat" : "" ,
"lon" : "" ,
"zoom" : "7" ,
"layer" : "Nat Geo" ,
2020-07-14 18:22:31 +02:00
"cluster" : "1" ,
"maxage" : "" ,
"usermenu" : "hide" ,
"layers" : "hide" ,
"panit" : "false" ,
"panlock" : "false" ,
"zoomlock" : "false" ,
"hiderightclick" : "true" ,
"coords" : "deg" ,
"showgrid" : "false" ,
"path" : "/worldmap" ,
"x" : 640 ,
"y" : 200 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b3e8d04.7c83d3" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "get object_lat & object_lon" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"func" : "error = Math.sqrt(msg.payload.epx**2+msg.payload.epy**2)\n\nmsg.payload = {\n \"name\":\"sailboat\",\n \"lat\":msg.payload.lat,\n \"lon\":msg.payload.lon,\n \"speed\":msg.payload.speed,\n \"bearing\":msg.payload.track,\n \"icon\":\"ship\",\n \"accuracy\":error,\n \"command\": { \"lat\":msg.payload.lat, \"lon\":msg.payload.lon,\n grid : {showgrid: true,\n opt: { showLabel:true, dashArray:[5, 5], fontColor:\"#900\" }\n }\n }\n};\n\nreturn msg;" ,
2020-07-14 18:22:31 +02:00
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 350 ,
2020-07-14 18:22:31 +02:00
"y" : 200 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"f7ae988c.184598"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9c08f843.b1e1b" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "set object_time" ,
"func" : "var time = new Date(msg.payload);\n\nvar hour = time.getUTCHours();\nif (hour<10){hour = \"0\"+hour;}\nvar minute = time.getUTCMinutes();\nif (minute<10){minute = \"0\"+minute;}\n\nvar time_UTC = \"\"+hour+minute;\nglobal.set('object_time',time_UTC);\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
2020-09-15 17:33:49 +02:00
"x" : 620 ,
2020-07-14 18:22:31 +02:00
"y" : 80 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "157ba5ca.c88a52" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "1a447be0.198674" ,
2020-07-14 18:22:31 +02:00
"name" : "set object_date" ,
"func" : "var date = new Date(msg.payload);\n\nvar year = date.getUTCFullYear();\nvar month = date.getUTCMonth()+1;\nif (month<10){month = \"0\"+month;}\nvar day = date.getUTCDate();\nif (day<10){day = \"0\"+day;}\n\nvar date_UTC = \"\"+year+month+day;\nglobal.set('object_date',date_UTC);\n\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
2020-09-15 17:33:49 +02:00
"x" : 620 ,
2020-07-14 18:22:31 +02:00
"y" : 40 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "701120fd.c5516" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "set optical config" ,
"func" : "global.set(msg.topic,msg.payload);\nvar acq_fnumber_objective = String(global.get(msg.topic));\n\nswitch(acq_fnumber_objective) {\n case \"25\":\n global.set(\"acq_magnification\",0.6);\n global.set(\"process_pixel\",1.86);\n global.set(\"sug_min\",60);\n global.set(\"sug_max\",670);\n global.set(\"sug_flowrate\",3);\n break;\n case \"16\":\n global.set(\"acq_magnification\",0.94);\n global.set(\"process_pixel\",1.19);\n global.set(\"sug_min\",40);\n global.set(\"sug_max\",430);\n global.set(\"sug_flowrate\",2.4);\n break;\n case \"12\":\n global.set(\"acq_magnification\",1.20);\n global.set(\"process_pixel\",0.94);\n global.set(\"sug_min\",30);\n global.set(\"sug_max\",340);\n global.set(\"sug_flowrate\",1.25);\n break;\n case \"8\":\n global.set(\"acq_magnification\",1.78);\n global.set(\"process_pixel\",0.63);\n global.set(\"sug_min\",20);\n global.set(\"sug_max\",230);\n global.set(\"sug_flowrate\",0.42);\n break;\n case \"6\":\n global.set(\"acq_magnification\",2.36);\n global.set(\"process_pixel\",0.48);\n global.set(\"sug_min\",15);\n global.set(\"sug_max\",170);\n global.set(\"sug_flowrate\",0.32);\n break;\n}\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 750 ,
"y" : 360 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "2554ff8e.8cf1a8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_dropdown" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_fnumber_objective" ,
"label" : "M12 Lens*" ,
"tooltip" : "" ,
"place" : "Select option" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 3 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"options" : [
{
"label" : "f 25mm 1/2\" 5MP IR" ,
"value" : 25 ,
"type" : "num"
} ,
{
"label" : "f 16mm 1/2.5\" 5MP IR" ,
"value" : 16 ,
"type" : "num"
} ,
{
"label" : "f 12mm 1/2.5\" 5MP IR" ,
"value" : 12 ,
"type" : "num"
} ,
{
"label" : "f 8mm 1/2.5\" 5MP IR" ,
"value" : 8 ,
"type" : "num"
} ,
{
"label" : "f 6mm 1/2.5\" 5MP IR" ,
"value" : 6 ,
"type" : "num"
}
] ,
"payload" : "" ,
"topic" : "acq_fnumber_objective" ,
"x" : 526 ,
"y" : 360 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"701120fd.c5516"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "2f9ae002.b4c96" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_minimum_mesh" ,
"label" : "Min fraction size (μm)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 8 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "acq_minimum_mesh" ,
"format" : "{{value}}" ,
"min" : 0 ,
"max" : "300" ,
"step" : "10" ,
"x" : 536 ,
"y" : 160 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c86d98d4.c56538" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_maximum_mesh" ,
"label" : "Max fraction size (μm)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 4 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "acq_maximum_mesh" ,
"format" : "{{value}}" ,
"min" : "200" ,
"max" : "2000" ,
"step" : "100" ,
"x" : 536 ,
"y" : 200 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "98d1f331.a06938" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_id" ,
"label" : "Acquisition unique ID*" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "acq_id" ,
"x" : 586 ,
"y" : 40 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "42505cbd.f02b1c" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_dropdown" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_celltype" ,
"label" : "Thickness flowcell*" ,
"tooltip" : "" ,
"place" : "Select option" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 7 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"options" : [
{
"label" : "200 μm µ-Slide I Luer" ,
"value" : 200 ,
"type" : "num"
} ,
{
"label" : "400 μm µ-Slide I Luer" ,
"value" : 400 ,
"type" : "num"
} ,
{
"label" : "600 μm µ-Slide I Luer" ,
"value" : 600 ,
"type" : "num"
} ,
{
"label" : "800 μm µ-Slide I Luer" ,
"value" : 800 ,
"type" : "num"
}
] ,
"payload" : "" ,
"topic" : "acq_celltype" ,
"x" : 566 ,
"y" : 120 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "13b51e1e.1f603a" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_volume" ,
"label" : "Volume to pass (ml)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 2 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "acq_volume" ,
"x" : 566 ,
"y" : 240 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3b9700c4.b93ec" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_instrument" ,
"label" : "Acquisition instrument" ,
"tooltip" : "PlanktonScope V2.1" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 6 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "text" ,
"delay" : 300 ,
"topic" : "acq_instrument" ,
"x" : 556 ,
"y" : 80 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f3658d30.b8448" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_id" ,
"func" : "msg.payload = msg.payload.acq_id+1;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 210 ,
"y" : 40 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"98d1f331.a06938"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5acd51d4.4ab13" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_instrument" ,
"func" : "msg.payload = msg.payload.acq_instrument;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 230 ,
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"3b9700c4.b93ec"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "de2c90cf.b73b08" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_celltype" ,
"func" : "msg.payload = msg.payload.acq_celltype;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 220 ,
"y" : 120 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"42505cbd.f02b1c"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5e3dec55.881074" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_minimum_mesh" ,
"func" : "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 250 ,
"y" : 160 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"2f9ae002.b4c96"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d3ca8847.4d1ae" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_maximum_mesh" ,
"func" : "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 250 ,
"y" : 200 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"c86d98d4.c56538"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1f133196.96564e" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_volume" ,
"func" : "msg.payload = msg.payload.acq_volume;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 220 ,
"y" : 240 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"13b51e1e.1f603a"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "68fa1227.dbdd5c" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_fnumber_objective" ,
"func" : "msg.payload = msg.payload.acq_fnumber_objective;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 260 ,
"y" : 360 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"2554ff8e.8cf1a8"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6c391d10.2f9744" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_min_esd" ,
"label" : "Minimum size to segment (μm)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 9 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "acq_min_esd" ,
"format" : "{{value}}" ,
"min" : 0 ,
"max" : "300" ,
"step" : "5" ,
"x" : 566 ,
"y" : 280 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "163df12e.f73f5f" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_numeric" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "acq_max_esd" ,
"label" : "Maximum size to segment (μm)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "4361c3b6.e2b7a4" ,
2020-07-14 18:22:31 +02:00
"order" : 5 ,
"width" : 0 ,
"height" : 0 ,
"wrap" : false ,
"passthru" : true ,
"topic" : "acq_max_esd" ,
"format" : "{{value}}" ,
"min" : "100" ,
"max" : "2000" ,
"step" : "5" ,
"x" : 556 ,
"y" : 320 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3414b477.4d711c" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_min_esd" ,
"func" : "msg.payload = msg.payload.acq_min_esd;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 230 ,
"y" : 280 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6c391d10.2f9744"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a52e7caf.6bde48" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "758bc08f.c57318" ,
2020-07-14 18:22:31 +02:00
"name" : "get acq_max_esd" ,
"func" : "msg.payload = msg.payload.acq_max_esd;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 230 ,
"y" : 320 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"163df12e.f73f5f"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3cb96380.e575ec" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "pump.js" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"func" : "state = global.get(\"state\");\n\nif (state == null){state=\"free\"}\n\nvar manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n \n}else if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n \n}else {\n volume = global.get(\"pump_manual_volume\");\n msg.volume = volume;\n flowrate = global.get(\"pump_flowrate\");\n msg.topic = \"actuator/pump\";\n \n if(state===\"free\"){\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":volume,\n \"flowrate\":flowrate};\n }\n}\nreturn msg;" ,
2020-07-14 18:22:31 +02:00
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
2020-07-14 18:22:31 +02:00
"x" : 640 ,
"y" : 140 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"43fa762d.35bcb"
2020-07-14 18:22:31 +02:00
]
] ,
"info" : "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktonScope/scripts/focus.py 650 up\n"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "517efd7f.811f44" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "BACKWARD" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "34f03c4a.abdf94" ,
2020-07-14 18:22:31 +02:00
"order" : 2 ,
"width" : 6 ,
"height" : 1 ,
"passthru" : false ,
"label" : "" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "arrow_back" ,
"payload" : "BACKWARD" ,
"payloadType" : "str" ,
"topic" : "actuator/pump" ,
"x" : 470 ,
"y" : 120 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"3cb96380.e575ec"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d5de2fb4.dc9d8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "FORWARD" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "34f03c4a.abdf94" ,
2020-07-14 18:22:31 +02:00
"order" : 4 ,
"width" : 6 ,
"height" : 1 ,
"passthru" : true ,
"label" : "" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "arrow_forward" ,
"payload" : "FORWARD" ,
"payloadType" : "str" ,
"topic" : "actuator/pump" ,
"x" : 470 ,
"y" : 160 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"3cb96380.e575ec"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "43fa762d.35bcb" ,
2020-07-14 18:22:31 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"property" : "topic" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "eq" ,
"v" : "actuator/pump" ,
"vt" : "str"
} ,
{
"t" : "eq" ,
"v" : "Missing entry :" ,
"vt" : "str"
}
] ,
"checkall" : "true" ,
"repair" : false ,
"outputs" : 2 ,
"x" : 770 ,
"y" : 140 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"bdc8ce57.de1f08"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"8bcce348.efc1a"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8bcce348.efc1a" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_toast" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"position" : "dialog" ,
"displayTime" : "3" ,
"highlight" : "" ,
"sendall" : true ,
"outputs" : 1 ,
"ok" : "OK" ,
"cancel" : "" ,
"raw" : false ,
"topic" : "" ,
"name" : "" ,
"x" : 930 ,
"y" : 160 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f162cc1b.985148" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "stop pump" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "34f03c4a.abdf94" ,
2020-07-14 18:22:31 +02:00
"order" : 5 ,
"width" : 4 ,
"height" : 1 ,
"passthru" : true ,
"label" : "STOP PUMP" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"payload" : "{\"action\":\"stop\"}" ,
"payloadType" : "json" ,
"topic" : "actuator/pump" ,
2020-07-14 18:22:31 +02:00
"x" : 470 ,
"y" : 200 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"c38103c0.9aaa18"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "bdc8ce57.de1f08" ,
2020-07-14 18:22:31 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
2020-07-14 18:22:31 +02:00
"x" : 910 ,
"y" : 120 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c38103c0.9aaa18" ,
2020-07-14 18:22:31 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
2020-07-14 18:22:31 +02:00
"x" : 610 ,
"y" : 200 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f1b85f22.ac673" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "pump_manual_volume" ,
"label" : "Volume to pass (ml)" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "34f03c4a.abdf94" ,
2020-07-14 18:22:31 +02:00
"order" : 3 ,
"width" : 8 ,
"height" : 1 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "pump_manual_volume" ,
2020-10-06 17:22:25 +02:00
"x" : 510 ,
2020-07-14 18:22:31 +02:00
"y" : 80 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8ae06f9a.4b253" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "get pump_manual_volume" ,
"func" : "msg.payload = msg.payload.pump_manual_volume;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 220 ,
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"f1b85f22.ac673"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b8bf2a9.be099d8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_slider" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "pump_flowrate" ,
"label" : "Flowrate (ml/min)*" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "34f03c4a.abdf94" ,
2020-07-14 18:22:31 +02:00
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"outs" : "end" ,
"topic" : "pump_flowrate" ,
2020-10-06 17:22:25 +02:00
"min" : "0.1" ,
"max" : "10" ,
2020-07-14 18:22:31 +02:00
"step" : "0.1" ,
2020-10-06 17:22:25 +02:00
"x" : 480 ,
2020-07-14 18:22:31 +02:00
"y" : 40 ,
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "cc757614.c8fc58" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "977131e7.c2e76" ,
2020-07-14 18:22:31 +02:00
"name" : "get pump_flowrate" ,
"func" : "msg.payload = msg.payload.pump_flowrate;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 190 ,
"y" : 40 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"b8bf2a9.be099d8"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f49b3397.2599f8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
"name" : "focus_distance" ,
"label" : "Distance in µm" ,
"tooltip" : "This will be rounded to the nearest 25µm" ,
"group" : "de7c8e82.7faa98" ,
2020-10-06 17:22:25 +02:00
"order" : 8 ,
2020-07-14 18:22:31 +02:00
"width" : 8 ,
"height" : 1 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"topic" : "focus_distance" ,
2020-07-14 18:22:31 +02:00
"x" : 540 ,
"y" : 40 ,
"wires" : [
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
[
"b69e435f.b93558"
]
2020-07-14 18:22:31 +02:00
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "411211be.745ef8" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
"name" : "get focus_distance" ,
"func" : "msg.payload = msg.payload.focus_distance;\nreturn msg;" ,
2020-07-14 18:22:31 +02:00
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 220 ,
2020-07-14 18:22:31 +02:00
"y" : 40 ,
"wires" : [
[
2020-10-06 17:22:25 +02:00
"f49b3397.2599f8" ,
"d9930546.489a58"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "30718b7.3986b74" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"name" : "DOWN" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "de7c8e82.7faa98" ,
2020-10-06 17:22:25 +02:00
"order" : 4 ,
"width" : 3 ,
2020-07-14 18:22:31 +02:00
"height" : 1 ,
"passthru" : true ,
"label" : "" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "arrow_downward" ,
"payload" : "DOWN" ,
"payloadType" : "str" ,
"topic" : "actuator/focus" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 280 ,
"y" : 320 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"ee01103f.f91b28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "e0e433da.64e4e8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"name" : "UP" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "de7c8e82.7faa98" ,
2020-10-06 17:22:25 +02:00
"order" : 2 ,
"width" : 3 ,
2020-07-14 18:22:31 +02:00
"height" : 1 ,
"passthru" : false ,
"label" : "" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "arrow_upwards" ,
"payload" : "UP" ,
"payloadType" : "str" ,
"topic" : "actuator/focus" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 290 ,
"y" : 281 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"ee01103f.f91b28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c46d3379.54e17" ,
2020-07-14 18:22:31 +02:00
"type" : "switch" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"property" : "topic" ,
"propertyType" : "msg" ,
"rules" : [
{
"t" : "eq" ,
"v" : "actuator/focus" ,
"vt" : "str"
} ,
{
"t" : "eq" ,
"v" : "Missing entry :" ,
"vt" : "str"
}
] ,
"checkall" : "true" ,
"repair" : false ,
"outputs" : 2 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 570 ,
"y" : 300 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"a8dfcfd1.c5863"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6e5f2b4e.fcbeac"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6e5f2b4e.fcbeac" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_toast" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"position" : "dialog" ,
"displayTime" : "3" ,
"highlight" : "" ,
"sendall" : true ,
"outputs" : 1 ,
"ok" : "OK" ,
"cancel" : "" ,
"raw" : false ,
"topic" : "" ,
"name" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 730 ,
"y" : 340 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ee01103f.f91b28" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"name" : "focus.js" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"func" : "state = global.get(\"state\");\n\nif (state == null){state=\"free\"}\n\nvar distance = global.get(\"focus_distance\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n}else {\n distance = global.get(\"focus_distance\");\n if(state===\"free\"){\n // msg.payload is UP or DOWN here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000)};\n }\n}\nreturn msg;" ,
2020-07-14 18:22:31 +02:00
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 420 ,
"y" : 300 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"c46d3379.54e17"
2020-07-14 18:22:31 +02:00
]
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b8a2ecb3.f4f5f" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_button" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-07-14 18:22:31 +02:00
"name" : "stop focus" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "de7c8e82.7faa98" ,
2020-10-06 17:22:25 +02:00
"order" : 6 ,
2020-07-14 18:22:31 +02:00
"width" : 4 ,
"height" : 1 ,
"passthru" : true ,
"label" : "STOP FOCUS" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"payload" : "{\"action\":\"stop\"}" ,
"payloadType" : "json" ,
"topic" : "actuator/focus" ,
"x" : 270 ,
"y" : 400 ,
2020-09-15 17:33:49 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"2c100d73.ac6fba"
2020-09-15 17:33:49 +02:00
]
]
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a8dfcfd1.c5863" ,
2020-09-15 17:33:49 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
"x" : 710 ,
"y" : 280 ,
2020-09-15 17:33:49 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "2c100d73.ac6fba" ,
2020-09-15 17:33:49 +02:00
"type" : "mqtt out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "a0f9bde.423644" ,
2020-09-15 17:33:49 +02:00
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"broker" : "8dc3722c.06efa8" ,
"x" : 410 ,
"y" : 400 ,
2020-09-15 17:33:49 +02:00
"wires" : [ ]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "67fc8b3f.96c6cc" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "sample_ship" ,
"label" : "Name of the ship" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "71c63dd4.311c44" ,
"order" : 3 ,
2020-07-14 18:22:31 +02:00
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "text" ,
"delay" : 300 ,
"topic" : "sample_ship" ,
"x" : 590 ,
2020-09-15 17:33:49 +02:00
"y" : 160 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "91a896c8.7c9fb8" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_dropdown" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "sample_sampling_gear" ,
"label" : "Sampling gear" ,
"tooltip" : "" ,
"place" : "Select" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "71c63dd4.311c44" ,
"order" : 5 ,
2020-07-14 18:22:31 +02:00
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"multiple" : true ,
2020-07-14 18:22:31 +02:00
"options" : [
{
"label" : "Plankton net" ,
"value" : "net" ,
"type" : "str"
} ,
{
"label" : "Niskin bottle 12L" ,
"value" : "niskin_12L" ,
"type" : "str"
} ,
{
"label" : "Niskin bottle 24L" ,
"value" : "niskin_24L" ,
"type" : "str"
} ,
{
"label" : "Pass Hull" ,
"value" : "pass_hull" ,
"type" : "str"
} ,
{
"label" : "Flask" ,
"value" : "flask" ,
"type" : "str"
}
] ,
"payload" : "" ,
"topic" : "sample_sampling_gear" ,
"x" : 550 ,
2020-09-15 17:33:49 +02:00
"y" : 240 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "8cc6c6f1.65bf28" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "sample_operator" ,
"label" : "Name of the operator" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "71c63dd4.311c44" ,
"order" : 4 ,
2020-07-14 18:22:31 +02:00
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "text" ,
"delay" : 300 ,
"topic" : "sample_operator" ,
"x" : 570 ,
2020-09-15 17:33:49 +02:00
"y" : 200 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "adaccbb2.320458" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "sample_project" ,
"label" : "Name of the project*" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "71c63dd4.311c44" ,
"order" : 2 ,
2020-07-14 18:22:31 +02:00
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "text" ,
"delay" : 300 ,
"topic" : "sample_project" ,
"x" : 580 ,
2020-09-15 17:33:49 +02:00
"y" : 80 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a63c1b66.f9a77" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_text_input" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "sample_id" ,
"label" : "ID of the station*" ,
"tooltip" : "" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "71c63dd4.311c44" ,
"order" : 6 ,
2020-07-14 18:22:31 +02:00
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"mode" : "number" ,
"delay" : 300 ,
"topic" : "sample_id" ,
"x" : 590 ,
2020-09-15 17:33:49 +02:00
"y" : 120 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d027a6bf.7049e8" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "get sample_projet" ,
"func" : "msg.payload = msg.payload.sample_project;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 250 ,
2020-09-15 17:33:49 +02:00
"y" : 80 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"adaccbb2.320458"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5a811caf.0f3144" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "get sample_ship" ,
"func" : "msg.payload = msg.payload.sample_ship;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
2020-10-06 17:22:25 +02:00
"x" : 250 ,
2020-09-15 17:33:49 +02:00
"y" : 160 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"67fc8b3f.96c6cc"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "45911c98.2bd83c" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "get sample_id" ,
"func" : "msg.payload = msg.payload.sample_id+1;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 240 ,
2020-09-15 17:33:49 +02:00
"y" : 120 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"a63c1b66.f9a77"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1e09a4ab.72996b" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "get sample_operator" ,
"func" : "msg.payload = msg.payload.sample_operator;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 260 ,
2020-09-15 17:33:49 +02:00
"y" : 200 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"8cc6c6f1.65bf28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "a3272681.f271c8" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
2020-07-14 18:22:31 +02:00
"name" : "get sample_sampling_gear" ,
"func" : "msg.payload = msg.payload.sample_sampling_gear;\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"x" : 280 ,
2020-09-15 17:33:49 +02:00
"y" : 240 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"91a896c8.7c9fb8"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "10bfbbf.494c244" ,
2020-09-15 17:33:49 +02:00
"type" : "ui_template" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "81483277.2521e" ,
"group" : "71c63dd4.311c44" ,
2020-10-06 17:22:25 +02:00
"name" : "Information message" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"order" : 1 ,
"width" : 24 ,
2020-10-06 17:22:25 +02:00
"height" : "1" ,
"format" : "<div layout=\"row\">Fill the different inputs concerning the sample you want to image.</div>" ,
2020-09-15 17:33:49 +02:00
"storeOutMessages" : true ,
"fwdInMessages" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"resendOnRefresh" : false ,
2020-09-15 17:33:49 +02:00
"templateScope" : "local" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"x" : 420 ,
2020-10-06 17:22:25 +02:00
"y" : 40 ,
2020-09-15 17:33:49 +02:00
"wires" : [
[ ]
]
2020-07-14 18:27:49 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6f6ad84e.d9222" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "get global" ,
"func" : "msg.payload={\n \n \"sample_project\":global.get(\"sample_project\"),\n \"sample_id\":global.get(\"sample_id\"),\n \"sample_ship\":global.get(\"sample_ship\"),\n \"sample_operator\":global.get(\"sample_operator\"),\n \"sample_sampling_gear\":global.get(\"sample_sampling_gear\"),\n \n \"acq_id\":global.get(\"acq_id\"),\n \"acq_instrument\":global.get(\"acq_instrument\"),\n //\"acq_instrument_id\":global.get(\"acq_instrument_id\"),\n \"acq_celltype\":global.get(\"acq_celltype\"),\n \"acq_minimum_mesh\":global.get(\"acq_minimum_mesh\"),\n \"acq_maximum_mesh\":global.get(\"acq_maximum_mesh\"),\n \"acq_min_esd\":global.get(\"acq_min_esd\"),\n \"acq_max_esd\":global.get(\"acq_max_esd\"),\n \"acq_volume\":global.get(\"acq_volume\"),\n \"acq_magnification\":global.get(\"magnification\"),\n \"acq_fnumber_objective\":global.get(\"acq_fnumber_objective\"),\n \n \"acq_camera_name\":\"Pi Camera V2.1 - 8MP\",\n \n \"object_date\":global.get(\"object_date\"),\n \"object_time\":global.get(\"object_time\"),\n \"object_lat\":global.get(\"object_lat\"),\n \"object_lon\":global.get(\"object_lon\"),\n \"object_depth_min\":global.get(\"object_depth_min\"),\n \"object_depth_max\":global.get(\"object_depth_max\"),\n \n \"custom_nb_frame\":global.get(\"custom_nb_frame\"),\n \"custom_nb_step\":global.get(\"custom_nb_step\"),\n \"custom_segmentation\":global.get(\"custom_segmentation\"),\n \"custom_sleep_before\":global.get(\"custom_sleep_before\"),\n \"focus_nb_step\":global.get(\"focus_nb_step\"),\n \"pump_flowrate\":global.get(\"pump_flowrate\"),\n \"pump_manual_volume\":global.get(\"pump_manual_volume\"),\n \n \"process_pixel\":global.get(\"process_pixel\"),\n \"process_id\":global.get(\"process_id\")\n \n \n};\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 1300 ,
"y" : 220 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"7cd7b4d0.cfc56c"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "bb1b1e3.906e7e" ,
2020-07-14 18:22:31 +02:00
"type" : "file" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"filename" : "/home/pi/PlanktonScope/config.json" ,
"appendNewline" : true ,
"createDir" : true ,
"overwriteFile" : "true" ,
"encoding" : "none" ,
2020-10-06 17:22:25 +02:00
"x" : 1710 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 220 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "7cd7b4d0.cfc56c" ,
2020-07-14 18:22:31 +02:00
"type" : "json" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "config.json" ,
"property" : "payload" ,
"action" : "str" ,
"pretty" : true ,
2020-10-06 17:22:25 +02:00
"x" : 1460 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 220 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"bb1b1e3.906e7e"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "83f2e27a.b59688" ,
2020-07-14 18:22:31 +02:00
"type" : "file in" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"filename" : "/home/pi/PlanktonScope/config.json" ,
"format" : "utf8" ,
"chunk" : false ,
"sendError" : false ,
"encoding" : "none" ,
2020-10-06 17:22:25 +02:00
"x" : 370 ,
2020-07-14 18:22:31 +02:00
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"3333aa46.5fa3ee"
2020-07-14 18:22:31 +02:00
]
] ,
"info" : "# PlanktonScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9db37b60.5e5488" ,
2020-07-14 18:22:31 +02:00
"type" : "inject" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "on_load" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"props" : [
{
"p" : "payload"
} ,
{
"p" : "topic" ,
"vt" : "str"
}
] ,
2020-07-14 18:22:31 +02:00
"repeat" : "" ,
"crontab" : "" ,
"once" : true ,
"onceDelay" : 0.1 ,
2020-09-15 17:33:49 +02:00
"topic" : "" ,
"payload" : "" ,
"payloadType" : "date" ,
2020-07-14 18:22:31 +02:00
"x" : 120 ,
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"83f2e27a.b59688" ,
"172d187b.ad216"
2020-07-14 18:22:31 +02:00
]
] ,
"info" : "# PlanktonScope Help\nWhen the **Pi** is booting, **Node-RED** will be initiated and this node will be activated once and execute the following nodes."
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "3333aa46.5fa3ee" ,
2020-07-14 18:22:31 +02:00
"type" : "json" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "config.json" ,
"property" : "payload" ,
"action" : "" ,
"pretty" : false ,
"x" : 610 ,
"y" : 80 ,
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"1f2d3f3d.5eeff9" ,
"64b58fc8.cdc4e" ,
"c94db91f.7cf2b8" ,
"70625f12.179948" ,
"f56b39e5.245b4" ,
"24a381c3.761f56" ,
"6a7bbade.f3174c"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6725d70.a4aed28" ,
2020-07-14 18:22:31 +02:00
"type" : "function" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "set global" ,
"func" : "var value = msg.payload;\nvar key = msg.topic;\n\nglobal.set(key,value);\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"initialize" : "" ,
"finalize" : "" ,
"x" : 1300 ,
"y" : 140 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6f6ad84e.d9222"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "9f81fc0f.814988" ,
2020-07-14 18:22:31 +02:00
"type" : "rpi-gpio out" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-10-06 17:22:25 +02:00
"name" : "LED OUTPUT" ,
2020-07-14 18:22:31 +02:00
"pin" : "40" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"set" : true ,
2020-07-14 18:22:31 +02:00
"level" : "0" ,
"freq" : "" ,
"out" : "out" ,
2020-10-06 17:22:25 +02:00
"x" : 540 ,
2020-09-15 17:33:49 +02:00
"y" : 180 ,
2020-07-14 18:22:31 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "60cc050b.8dae74" ,
2020-07-14 18:22:31 +02:00
"type" : "ui_template" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
"group" : "59434d8d.70ed94" ,
2020-07-14 18:22:31 +02:00
"name" : "Stream Pi Camera" ,
"order" : 1 ,
"width" : 24 ,
2020-09-15 17:33:49 +02:00
"height" : 19 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"format" : "<center>\n <img src=\"http://planktoscope.local:8000/stream.mjpg\"\n width=\"100%\" height=\"100%\">\n</center>" ,
2020-07-14 18:22:31 +02:00
"storeOutMessages" : true ,
"fwdInMessages" : true ,
2020-09-15 17:33:49 +02:00
"resendOnRefresh" : false ,
2020-07-14 18:22:31 +02:00
"templateScope" : "local" ,
2020-09-15 17:33:49 +02:00
"x" : 930 ,
"y" : 440 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[ ]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1f2d3f3d.5eeff9" ,
"type" : "subflow:81483277.2521e" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 930 ,
"y" : 140 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "24a381c3.761f56" ,
"type" : "subflow:a0f9bde.423644" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 920 ,
"y" : 360 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "6a7bbade.f3174c" ,
"type" : "subflow:977131e7.c2e76" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 920 ,
"y" : 400 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "64b58fc8.cdc4e" ,
"type" : "subflow:758bc08f.c57318" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 940 ,
"y" : 180 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6f6ad84e.d9222"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "c94db91f.7cf2b8" ,
"type" : "subflow:1a447be0.198674" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-10-06 17:22:25 +02:00
"x" : 930 ,
2020-09-15 17:33:49 +02:00
"y" : 220 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
] ,
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6f6ad84e.d9222"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f1f6f8ca.a80bd" ,
"type" : "subflow:9c3e6ad4.7471a8" ,
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "RPi commands" ,
2020-07-14 18:22:31 +02:00
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 920 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 820 ,
2020-07-14 18:22:31 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b8638c84.bcd58" ,
"type" : "subflow:bee3b478.ef4b88" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 320 ,
"y" : 320 ,
2020-07-14 18:22:31 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "70625f12.179948" ,
"type" : "subflow:714bd4fe.163ab4" ,
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Process metadata" ,
2020-07-14 18:22:31 +02:00
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 930 ,
"y" : 260 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
]
]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "f56b39e5.245b4" ,
"type" : "subflow:1bc3f9f9.1ee996" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "Acquisition inputs" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 930 ,
"y" : 540 ,
2020-07-14 18:22:31 +02:00
"wires" : [
[
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"6725d70.a4aed28"
2020-07-14 18:22:31 +02:00
]
] ,
"icon" : "node-red-dashboard/ui_switch.png"
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "590670c8.5b17c" ,
"type" : "subflow:130e0533.4f1813" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-10-06 17:22:25 +02:00
"x" : 940 ,
2020-09-15 17:33:49 +02:00
"y" : 580 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b902251f.c756f" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Inject config.json in GUI inputs" ,
"info" : "" ,
"x" : 660 ,
"y" : 40 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "e824bf49.c0716" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Edit config.json on changes" ,
"info" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 1320 ,
2020-09-15 17:33:49 +02:00
"y" : 40 ,
2020-07-14 18:22:31 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5836c9be.895de8" ,
"type" : "subflow:21b3da63.2cef2e" ,
"z" : "e8d4d920.35344" ,
2020-07-14 18:22:31 +02:00
"name" : "" ,
"env" : [ ] ,
2020-09-15 17:33:49 +02:00
"x" : 920 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 860 ,
2020-07-14 18:22:31 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "b94ee83b.5fc548" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Create and run python code receiving MQTT queries" ,
"info" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 420 ,
2020-09-15 17:33:49 +02:00
"y" : 240 ,
"wires" : [ ]
2020-07-14 18:22:31 +02:00
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "61f01a83.88da5c" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "On Load" ,
"info" : "" ,
"x" : 120 ,
"y" : 40 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "fa75a682.73df7" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Get metadata from config.json" ,
"info" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 350 ,
2020-09-15 17:33:49 +02:00
"y" : 40 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "5d22882.f86d2f8" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-10-06 17:22:25 +02:00
"name" : "White LED control" ,
2020-09-15 17:33:49 +02:00
"info" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 310 ,
2020-09-15 17:33:49 +02:00
"y" : 140 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "d418fabe.d0b75" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Visible on the GUI" ,
"info" : "" ,
"x" : 930 ,
"y" : 40 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "ac2a06c3.0eec2" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "RPi" ,
"info" : "" ,
"x" : 890 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 780 ,
2020-09-15 17:33:49 +02:00
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "630ed3ce.35374c" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Metadata" ,
"info" : "" ,
"x" : 900 ,
"y" : 100 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "1fc17ae3.11b69d" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Actuation" ,
"info" : "" ,
"x" : 900 ,
"y" : 320 ,
"wires" : [ ]
} ,
{
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"id" : "dada61e7.83ee38" ,
2020-09-15 17:33:49 +02:00
"type" : "comment" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"z" : "e8d4d920.35344" ,
2020-09-15 17:33:49 +02:00
"name" : "Acquisition" ,
"info" : "" ,
"x" : 900 ,
"y" : 500 ,
"wires" : [ ]
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
} ,
{
"id" : "f44de853.0c855" ,
"type" : "ui_switch" ,
"z" : "e8d4d920.35344" ,
"name" : "" ,
"label" : "LED" ,
"tooltip" : "" ,
"group" : "59434d8d.70ed94" ,
2020-10-06 17:22:25 +02:00
"order" : 2 ,
"width" : 0 ,
"height" : 0 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"passthru" : true ,
"decouple" : "false" ,
"topic" : "" ,
"style" : "" ,
"onvalue" : "true" ,
"onvalueType" : "bool" ,
"onicon" : "" ,
"oncolor" : "" ,
"offvalue" : "false" ,
"offvalueType" : "bool" ,
"officon" : "" ,
"offcolor" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 390 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 180 ,
"wires" : [
[
"9f81fc0f.814988"
]
]
} ,
{
"id" : "22392d.ef1a66d4" ,
"type" : "status" ,
"z" : "1a447be0.198674" ,
"name" : "GPS Status" ,
"scope" : [
"cb77803f.357f88"
] ,
"x" : 110 ,
2020-10-06 17:22:25 +02:00
"y" : 560 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [
[
"a30fe92c.6b73e8"
]
]
} ,
{
"id" : "a30fe92c.6b73e8" ,
"type" : "ui_text" ,
"z" : "1a447be0.198674" ,
2020-10-06 17:22:25 +02:00
"group" : "7b7849e8.363288" ,
"order" : 2 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : 6 ,
"height" : 1 ,
"name" : "GPS Status Display" ,
"label" : "GPS Status:" ,
"format" : "{{msg.status.text}}" ,
"layout" : "row-left" ,
2020-10-06 17:22:25 +02:00
"x" : 600 ,
"y" : 560 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [ ]
} ,
{
"id" : "ec0d715e.19fdd" ,
"type" : "ui_text" ,
"z" : "1a447be0.198674" ,
2020-10-06 17:22:25 +02:00
"group" : "7b7849e8.363288" ,
"order" : 3 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : 6 ,
"height" : 1 ,
"name" : "Latitude" ,
"label" : "Latitude" ,
"format" : "{{msg.payload.lat.deg}}°{{msg.payload.lat.min}}'{{msg.payload.lat.sec}}{{msg.payload.lat.dir}}" ,
"layout" : "row-left" ,
"x" : 640 ,
2020-10-06 17:22:25 +02:00
"y" : 340 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [ ]
} ,
{
"id" : "f8c5f7ef.e93908" ,
"type" : "ui_text" ,
"z" : "1a447be0.198674" ,
2020-10-06 17:22:25 +02:00
"group" : "7b7849e8.363288" ,
"order" : 4 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"width" : 6 ,
"height" : 1 ,
"name" : "Longitude" ,
"label" : "Longitude" ,
"format" : "{{msg.payload.lon.deg}}°{{msg.payload.lon.min}}'{{msg.payload.lon.sec}}{{msg.payload.lon.dir}}" ,
"layout" : "row-right" ,
"x" : 640 ,
2020-10-06 17:22:25 +02:00
"y" : 380 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [ ]
} ,
{
"id" : "3f718ceb.5e9f34" ,
"type" : "function" ,
"z" : "1a447be0.198674" ,
"name" : "Convert DD to DMS" ,
"func" : "function ConvertDDToDMS(D, lng){\n // from https://stackoverflow.com/a/5786281/2108279\n return {\n dir : D<0?lng?'W':'S':lng?'E':'N',\n deg : 0|(D<0?D=-D:D),\n min : 0|D%1*60,\n sec :(0|D*60%1*6000)/100\n };\n}\n\nmsg.payload = {\n \"lat\":ConvertDDToDMS(msg.payload.lat, false),\n \"lon\":ConvertDDToDMS(msg.payload.lon, true)\n};\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 350 ,
2020-10-06 17:22:25 +02:00
"y" : 360 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [
[
"ec0d715e.19fdd" ,
"f8c5f7ef.e93908"
]
]
} ,
{
"id" : "74554b33.14ab6c" ,
"type" : "file" ,
"z" : "1a447be0.198674" ,
2020-10-06 17:22:25 +02:00
"d" : true ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"name" : "gpsd_output" ,
"filename" : "/home/pi/gpsd.json" ,
"appendNewline" : true ,
"createDir" : false ,
"overwriteFile" : "false" ,
"x" : 630 ,
"y" : 240 ,
"wires" : [
[ ]
]
} ,
{
"id" : "b69e435f.b93558" ,
"type" : "function" ,
"z" : "a0f9bde.423644" ,
"name" : "round distance" ,
"func" : "// Here we change the focus_distance to 25 µm increment\nif (msg.payload%25 <= 12.5){\n msg.payload = msg.payload - msg.payload%25\n}\nelse {\n msg.payload = msg.payload + msg.payload%25\n}\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 820 ,
"y" : 40 ,
"wires" : [
[
"f49b3397.2599f8"
]
]
} ,
{
"id" : "2aa5b118.d75f2e" ,
"type" : "json" ,
"z" : "bee3b478.ef4b88" ,
"name" : "" ,
"property" : "payload" ,
"action" : "obj" ,
"pretty" : true ,
"x" : 210 ,
"y" : 300 ,
"wires" : [
[
"ecedbda4.fed15"
]
]
} ,
{
"id" : "1dd0c3dd.60236c" ,
"type" : "template" ,
"z" : "bee3b478.ef4b88" ,
"name" : "Create sentence" ,
"field" : "payload" ,
"fieldType" : "msg" ,
"format" : "handlebars" ,
"syntax" : "mustache" ,
"template" : "The {{topic}} is {{payload.status}}" ,
"output" : "str" ,
2020-10-06 17:22:25 +02:00
"x" : 1170 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 280 ,
"wires" : [
[
"1403e1a4.528926"
]
]
} ,
{
"id" : "117aad13.53e11b" ,
"type" : "change" ,
"z" : "bee3b478.ef4b88" ,
"name" : "Remove high-level topic" ,
"rules" : [
{
"t" : "change" ,
"p" : "topic" ,
"pt" : "msg" ,
"from" : "status/" ,
"fromt" : "str" ,
"to" : "" ,
"tot" : "str"
}
] ,
"action" : "" ,
"property" : "" ,
"from" : "" ,
"to" : "" ,
"reg" : false ,
2020-10-06 17:22:25 +02:00
"x" : 930 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 280 ,
"wires" : [
[
"1dd0c3dd.60236c"
]
]
} ,
{
"id" : "8ec68b82.17e3d8" ,
"type" : "ui_button" ,
"z" : "4b508eab.dccae8" ,
"name" : "Start segmentation" ,
"group" : "566dcd6a.03db74" ,
2020-10-06 17:22:25 +02:00
"order" : 1 ,
"width" : 16 ,
"height" : 1 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"passthru" : false ,
"label" : "Start segmentation" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "" ,
"payload" : "{\"action\":\"segment\"}" ,
"payloadType" : "json" ,
"topic" : "segmenter/segment" ,
"x" : 270 ,
"y" : 200 ,
"wires" : [
[
"16f3cef4.0acac9"
]
]
} ,
{
"id" : "27be7971.b3fbce" ,
"type" : "ui_button" ,
"z" : "4b508eab.dccae8" ,
"name" : "Stop segmentation" ,
"group" : "566dcd6a.03db74" ,
2020-10-06 17:22:25 +02:00
"order" : 2 ,
"width" : 8 ,
"height" : 1 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"passthru" : true ,
"label" : "Stop segmentation" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
"payload" : "{\"action\":\"stop\"}" ,
"payloadType" : "json" ,
"topic" : "segmenter/segment" ,
"x" : 270 ,
"y" : 320 ,
"wires" : [
[
"16f3cef4.0acac9"
]
]
} ,
{
"id" : "16f3cef4.0acac9" ,
"type" : "mqtt out" ,
"z" : "4b508eab.dccae8" ,
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
"broker" : "8dc3722c.06efa8" ,
"x" : 610 ,
"y" : 260 ,
"wires" : [ ]
} ,
{
"id" : "f8eade62.0eb118" ,
"type" : "subflow:4b508eab.dccae8" ,
"z" : "e8d4d920.35344" ,
"name" : "" ,
"env" : [ ] ,
2020-10-06 17:22:25 +02:00
"x" : 940 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 720 ,
"wires" : [ ]
} ,
{
"id" : "30fc0aaa.8fdd96" ,
"type" : "comment" ,
"z" : "e8d4d920.35344" ,
"name" : "Segmentation" ,
"info" : "" ,
"x" : 910 ,
"y" : 680 ,
"wires" : [ ]
} ,
{
"id" : "16aa0238.209276" ,
"type" : "ui_slider" ,
"z" : "674362b7.9b6574" ,
"name" : "Iso slider" ,
"label" : "ISO" ,
"tooltip" : "Possible values are 100, 200, 320, 400, 500, 640, 800" ,
"group" : "e8b67968.dea6" ,
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"outs" : "end" ,
"topic" : "imager/image" ,
"min" : "100" ,
"max" : "800" ,
"step" : "20" ,
"x" : 300 ,
"y" : 100 ,
"wires" : [
[
"bb090334.1e21a8"
]
]
} ,
{
"id" : "bb090334.1e21a8" ,
"type" : "function" ,
"z" : "674362b7.9b6574" ,
"name" : "round iso" ,
"func" : "// Iso should be one of 60, 100, 200, 320, 400, 500, 640, 800\n\nif (msg.payload <= 80){\n msg.payload = 60;\n return msg;\n}\n\nif (msg.payload <= 150){\n msg.payload = 100;\n return msg;\n}\n\nif (msg.payload <= 260){\n msg.payload = 200;\n return msg;\n}\n\nif (msg.payload <= 360){\n msg.payload = 320;\n return msg;\n}\n\nif (msg.payload <= 450){\n msg.payload = 400;\n return msg;\n}\n\nif (msg.payload <= 565){\n msg.payload = 500;\n return msg;\n}\n\nif (msg.payload <= 700){\n msg.payload = 640;\n return msg;\n}\n\n\nif (700 < msg.payload){\n msg.payload = 800;\n return msg;\n}\n" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 460 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 100 ,
"wires" : [
[
"16aa0238.209276" ,
"8ea9dc9a.c7d87"
]
]
} ,
{
"id" : "8ea9dc9a.c7d87" ,
"type" : "function" ,
"z" : "674362b7.9b6574" ,
"name" : "Encapsulate settings" ,
"func" : "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"iso\":msg.payload}\n}\nmsg.topic = \"imager/image\"\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 660 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 100 ,
"wires" : [
[
"845e06e1.0d812"
]
]
} ,
{
"id" : "5765a825.a595c8" ,
"type" : "ui_slider" ,
"z" : "674362b7.9b6574" ,
"name" : "Shutter speed slider" ,
"label" : "Shutter Speed" ,
2020-10-06 17:22:25 +02:00
"tooltip" : "In microseconds, up to 5000µs, 10µs by default" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"group" : "e8b67968.dea6" ,
"order" : 2 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"outs" : "end" ,
"topic" : "imager/image" ,
"min" : "10" ,
"max" : "5000" ,
"step" : "10" ,
"x" : 340 ,
"y" : 220 ,
"wires" : [
[
"c38509b.fb08af8"
]
]
} ,
{
"id" : "c38509b.fb08af8" ,
"type" : "function" ,
"z" : "674362b7.9b6574" ,
"name" : "Encapsulate settings" ,
"func" : "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"shutter_speed\":msg.payload}\n}\nmsg.topic = \"imager/image\"\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
2020-10-06 17:22:25 +02:00
"x" : 660 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 220 ,
"wires" : [
[
"845e06e1.0d812"
]
]
} ,
{
"id" : "845e06e1.0d812" ,
"type" : "mqtt out" ,
"z" : "674362b7.9b6574" ,
"name" : "" ,
"topic" : "" ,
"qos" : "" ,
"retain" : "" ,
"broker" : "8dc3722c.06efa8" ,
2020-10-06 17:22:25 +02:00
"x" : 950 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 160 ,
"wires" : [ ]
} ,
{
"id" : "2350e507.d4e302" ,
"type" : "inject" ,
"z" : "674362b7.9b6574" ,
"name" : "" ,
"props" : [
{
"p" : "payload"
}
] ,
"repeat" : "" ,
"crontab" : "" ,
"once" : true ,
"onceDelay" : "1" ,
"topic" : "" ,
2020-10-06 17:22:25 +02:00
"payload" : "10" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"payloadType" : "num" ,
2020-10-06 17:22:25 +02:00
"x" : 110 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"y" : 220 ,
"wires" : [
[
"5765a825.a595c8"
]
]
} ,
{
"id" : "2edd922b.a471a6" ,
"type" : "inject" ,
"z" : "674362b7.9b6574" ,
"name" : "" ,
"props" : [
{
"p" : "payload"
}
] ,
"repeat" : "" ,
"crontab" : "" ,
"once" : true ,
"onceDelay" : "1" ,
"topic" : "" ,
2020-10-06 17:22:25 +02:00
"payload" : "500" ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"payloadType" : "num" ,
"x" : 110 ,
"y" : 100 ,
"wires" : [
[
"16aa0238.209276"
]
]
} ,
{
"id" : "649552a6.bf68fc" ,
"type" : "subflow:674362b7.9b6574" ,
"z" : "e8d4d920.35344" ,
"name" : "" ,
"env" : [ ] ,
"x" : 920 ,
2020-10-06 17:22:25 +02:00
"y" : 620 ,
"wires" : [ ]
} ,
{
"id" : "bb62da8a.ebc328" ,
"type" : "ui_switch" ,
"z" : "130e0533.4f1813" ,
"name" : "" ,
"label" : "Pump FORWARD/BACKWARD" ,
"tooltip" : "" ,
"group" : "75a5ce1f.728d" ,
"order" : 3 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : true ,
"decouple" : "false" ,
"topic" : "" ,
"style" : "" ,
"onvalue" : "FORWARD" ,
"onvalueType" : "str" ,
"onicon" : "" ,
"oncolor" : "" ,
"offvalue" : "BACKWARD" ,
"offvalueType" : "str" ,
"officon" : "" ,
"offcolor" : "" ,
"x" : 150 ,
"y" : 180 ,
"wires" : [
[ ]
]
} ,
{
"id" : "743041f8.d2b9b" ,
"type" : "inject" ,
"z" : "e8d4d920.35344" ,
"name" : "OFF" ,
"props" : [
{
"p" : "payload"
}
] ,
"repeat" : "" ,
"crontab" : "" ,
"once" : false ,
"onceDelay" : 0.1 ,
"topic" : "" ,
"payload" : "false" ,
"payloadType" : "bool" ,
"x" : 270 ,
"y" : 180 ,
"wires" : [
[
"f44de853.0c855"
]
]
} ,
{
"id" : "f6fd015e.5c1fe" ,
"type" : "debug" ,
"z" : "bee3b478.ef4b88" ,
"name" : "segmenter area" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "payload" ,
"targetType" : "msg" ,
"statusVal" : "" ,
"statusType" : "auto" ,
"x" : 1320 ,
"y" : 660 ,
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
"wires" : [ ]
2020-10-06 17:22:25 +02:00
} ,
{
"id" : "9998aa86.74bb" ,
"type" : "exec" ,
"z" : "d95291dc.83b0b8" ,
"command" : "python3 /home/pi/PlanktonScope/scripts/main.py" ,
"addpay" : false ,
"append" : "" ,
"useSpawn" : "true" ,
"timer" : "" ,
"oldrc" : false ,
"name" : "" ,
"x" : 830 ,
"y" : 140 ,
"wires" : [
[ ] ,
[ ] ,
[
"de4ba211.e1d3f"
]
]
} ,
{
"id" : "35ded403.3d7244" ,
"type" : "template" ,
"z" : "d95291dc.83b0b8" ,
"name" : "main.py" ,
"field" : "payload" ,
"fieldType" : "msg" ,
"format" : "python" ,
"syntax" : "plain" ,
"template" : "#Library to send command over I2C for the light module on the fan and subprocess to run bash command\nimport smbus, subprocess\n################################################################################\n#LEDs Actuation\n################################################################################\n\n#define the bus used to actuate the light module on the fan\nbus = smbus.SMBus(1)\n\ndef rgb(R,G,B):\n #Update LED n1\n bus.write_byte_data(0x0d, 0x00, 0)\n bus.write_byte_data(0x0d, 0x01, R)\n bus.write_byte_data(0x0d, 0x02, G)\n bus.write_byte_data(0x0d, 0x03, B)\n\n #Update LED n2\n bus.write_byte_data(0x0d, 0x00, 1)\n bus.write_byte_data(0x0d, 0x01, R)\n bus.write_byte_data(0x0d, 0x02, G)\n bus.write_byte_data(0x0d, 0x03, B)\n\n #Update LED n3\n bus.write_byte_data(0x0d, 0x00, 2)\n bus.write_byte_data(0x0d, 0x01, R)\n bus.write_byte_data(0x0d, 0x02, G)\n bus.write_byte_data(0x0d, 0x03, B)\n\n #Update the I2C Bus in order to really update the LEDs new values\n cmd=\"i2cdetect -y 1\" \ n s u b p r o c e s s . P o p e n ( c m d . s p l i t ( ) , s t d o u t = s u b p r o c e s s . P I P E ) \ n \ n # P r e s e n t t h e R E D c o l o r \ n r g b ( 255 , 0 , 0 ) \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # A c t u a t o r L i b r a r i e s \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \ n # L i b r a r y f o r e x c h a n i n g m e s s a g e s w i t h N o d e - R E D \ n i m p o r t p a h o . m q t t . c l i e n t a s m q t t \ n \ n # L i b r a r y t o c o n t r o l t h e P i C a m e r a \ n f r o m p i c a m e r a i m p o r t P i C a m e r a \ n \ n # L i b r a r i e s t o c o n t r o l t h e s t e p p e r s f o r f o c u s i n g a n d p u m p i n g \ n f r o m a d a f r u i t _ m o t o r i m p o r t s t e p p e r \ n f r o m a d a f r u i t _ m o t o r k i t i m p o r t M o t o r K i t \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # P r a c t i c a l L i b r a r i e s \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \ n # L i b r a r y t o g e t d a t e a n d t i m e f o r f o l d e r n a m e a n d f i l e n a m e \ n f r o m d a t e t i m e i m p o r t d a t e t i m e , t i m e d e l t a \ n \ n # L i b r a r y t o b e a b l e t o s l e e p f o r a d u r a t i o n \ n f r o m t i m e i m p o r t s l e e p \ n \ n # L i b r a r i e s m a n i p u l a t e j s o n f o r m a t , e x e c u t e b a s h c o m m a n d s \ n i m p o r t j s o n , s h u t i l , o s \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # M o r p h o c u t L i b r a r i e s \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \ n f r o m s k i m a g e . u t i l i m p o r t i m g _ a s _ u b y t e \ n f r o m m o r p h o c u t i m p o r t C a l l \ n f r o m m o r p h o c u t . c o n t r i b . e c o t a x a i m p o r t E c o t a x a W r i t e r \ n f r o m m o r p h o c u t . c o n t r i b . z o o p r o c e s s i m p o r t C a l c u l a t e Z o o P r o c e s s F e a t u r e s \ n f r o m m o r p h o c u t . c o r e i m p o r t P i p e l i n e \ n f r o m m o r p h o c u t . f i l e i m p o r t F i n d \ n f r o m m o r p h o c u t . i m a g e i m p o r t ( E x t r a c t R O I , \ n F i n d R e g i o n s , \ n I m a g e R e a d e r , \ n I m a g e W r i t e r , \ n R e s c a l e I n t e n s i t y , \ n R G B 2 G r a y \ n ) \ n f r o m m o r p h o c u t . s t a t i m p o r t R u n n i n g M e d i a n \ n f r o m m o r p h o c u t . s t r i m p o r t F o r m a t \ n f r o m m o r p h o c u t . s t r e a m i m p o r t T Q D M , E n u m e r a t e , F i l t e r V a r i a b l e s \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # O t h e r i m a g e p r o c e s s i n g L i b r a r i e s \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n \ n f r o m s k i m a g e . f e a t u r e i m p o r t c a n n y \ n f r o m s k i m a g e . c o l o r i m p o r t r g b 2 g r a y , l a b e l 2 r g b \ n f r o m s k i m a g e . m o r p h o l o g y i m p o r t d i s k \ n f r o m s k i m a g e . m o r p h o l o g y i m p o r t e r o s i o n , d i l a t i o n , c l o s i n g \ n f r o m s k i m a g e . m e a s u r e i m p o r t l a b e l , r e g i o n p r o p s \ n i m p o r t c v 2 \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # S t r e a m i n g P i C a m e r a o v e r s e r v e r \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n i m p o r t i o \ n i m p o r t p i c a m e r a \ n i m p o r t l o g g i n g \ n i m p o r t s o c k e t s e r v e r \ n f r o m t h r e a d i n g i m p o r t C o n d i t i o n \ n f r o m h t t p i m p o r t s e r v e r \ n i m p o r t t h r e a d i n g \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # G e t p o s s i b i l i t y t o g e n e r a t e r a n d o m n u m b e r s \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # g e n e r a t e r a n d o m i n t e g e r v a l u e s \ n f r o m r a n d o m i m p o r t s e e d \ n f r o m r a n d o m i m p o r t r a n d i n t \ n \ n \ n \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \ n # C r e a t i o n o f t h e w e b p a g e c o n t a i n i n g t h e P i C a m e r a S t r e a m i n g \ n # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
"output" : "str" ,
"x" : 760 ,
"y" : 340 ,
"wires" : [
[ ]
]
} ,
{
"id" : "672d89a8.4e6968" ,
"type" : "exec" ,
"z" : "d95291dc.83b0b8" ,
"command" : "sudo killall -9 python3" ,
"addpay" : true ,
"append" : "" ,
"useSpawn" : "false" ,
"timer" : "" ,
"oldrc" : false ,
"name" : "Hard kill" ,
"x" : 1280 ,
"y" : 100 ,
"wires" : [
[ ] ,
[ ] ,
[ ]
]
} ,
{
"id" : "172d187b.ad216" ,
"type" : "subflow:d95291dc.83b0b8" ,
"z" : "e8d4d920.35344" ,
"name" : "" ,
"env" : [ ] ,
"x" : 300 ,
"y" : 280 ,
"wires" : [ ]
} ,
{
"id" : "afa9f4b.2e77988" ,
"type" : "delay" ,
"z" : "d95291dc.83b0b8" ,
"name" : "" ,
"pauseType" : "delay" ,
"timeout" : "5" ,
"timeoutUnits" : "seconds" ,
"rate" : "1" ,
"nbRateUnits" : "1" ,
"rateUnits" : "second" ,
"randomFirst" : "1" ,
"randomLast" : "5" ,
"randomUnits" : "seconds" ,
"drop" : false ,
"x" : 420 ,
"y" : 140 ,
"wires" : [
[
"9998aa86.74bb"
]
]
} ,
{
"id" : "1df370a8.6c70ff" ,
"type" : "ui_button" ,
"z" : "d95291dc.83b0b8" ,
"name" : "Restart Python" ,
"group" : "adcd0ef7.81a7f8" ,
"order" : 1 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : false ,
"label" : "Restart Python" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "#AD1625" ,
"icon" : "" ,
"payload" : "" ,
"payloadType" : "str" ,
"topic" : "" ,
"x" : 100 ,
"y" : 140 ,
"wires" : [
[
"afa9f4b.2e77988" ,
"39edf8d2.bc92e8"
]
]
} ,
{
"id" : "39edf8d2.bc92e8" ,
"type" : "function" ,
"z" : "d95291dc.83b0b8" ,
"name" : "" ,
"func" : "msg.kill = \"SIGTERM\";\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 420 ,
"y" : 200 ,
"wires" : [
[
"9998aa86.74bb" ,
"de4ba211.e1d3f" ,
"a776b9fc.d542e8"
]
]
} ,
{
"id" : "de4ba211.e1d3f" ,
"type" : "debug" ,
"z" : "d95291dc.83b0b8" ,
"name" : "output" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "payload" ,
"targetType" : "msg" ,
"statusVal" : "" ,
"statusType" : "auto" ,
"x" : 1270 ,
"y" : 200 ,
"wires" : [ ]
} ,
{
"id" : "7aa2e737.e16d98" ,
"type" : "status" ,
"z" : "d95291dc.83b0b8" ,
"name" : "" ,
"scope" : [
"9998aa86.74bb"
] ,
"x" : 960 ,
"y" : 260 ,
"wires" : [
[
"439b952c.3e9cf4"
]
]
} ,
{
"id" : "439b952c.3e9cf4" ,
"type" : "debug" ,
"z" : "d95291dc.83b0b8" ,
"name" : "status" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "status" ,
"targetType" : "msg" ,
"statusVal" : "" ,
"statusType" : "auto" ,
"x" : 1270 ,
"y" : 260 ,
"wires" : [ ]
} ,
{
"id" : "631688df.6f74c" ,
"type" : "ui_switch" ,
"z" : "1a447be0.198674" ,
"name" : "" ,
"label" : "Manual input" ,
"tooltip" : "" ,
"group" : "7b7849e8.363288" ,
"order" : 1 ,
"width" : 4 ,
"height" : 1 ,
"passthru" : true ,
"decouple" : "false" ,
"topic" : "" ,
"style" : "" ,
"onvalue" : "true" ,
"onvalueType" : "bool" ,
"onicon" : "" ,
"oncolor" : "" ,
"offvalue" : "false" ,
"offvalueType" : "bool" ,
"officon" : "" ,
"offcolor" : "" ,
"x" : 110 ,
"y" : 460 ,
"wires" : [
[
"c05c94eb.25471"
]
]
} ,
{
"id" : "c05c94eb.25471" ,
"type" : "function" ,
"z" : "1a447be0.198674" ,
"name" : "Enable Invert" ,
"func" : "msg.enabled = !msg.payload;\nmsg.payload = \"\"\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 320 ,
"y" : 460 ,
"wires" : [
[
"ec0d715e.19fdd" ,
"1b5cd285.71fa15" ,
"f8c5f7ef.e93908"
]
]
} ,
{
"id" : "6d0acc39.1d2e9c" ,
"type" : "ui_text_input" ,
"z" : "1a447be0.198674" ,
"name" : "Lat Manual" ,
"label" : "Latitude" ,
"tooltip" : "" ,
"group" : "7b7849e8.363288" ,
"order" : 7 ,
"width" : 12 ,
"height" : 1 ,
"passthru" : false ,
"mode" : "text" ,
"delay" : "2000" ,
"topic" : "latitude" ,
"x" : 650 ,
"y" : 460 ,
"wires" : [
[ ]
]
} ,
{
"id" : "1b5cd285.71fa15" ,
"type" : "change" ,
"z" : "1a447be0.198674" ,
"name" : "invert" ,
"rules" : [
{
"t" : "set" ,
"p" : "enabled" ,
"pt" : "msg" ,
"to" : "$not(msg.enabled)" ,
"tot" : "jsonata"
}
] ,
"action" : "" ,
"property" : "" ,
"from" : "" ,
"to" : "" ,
"reg" : false ,
"x" : 490 ,
"y" : 480 ,
"wires" : [
[
"6d0acc39.1d2e9c" ,
"8c2f9e2.0f3cd6"
]
]
} ,
{
"id" : "8c2f9e2.0f3cd6" ,
"type" : "ui_text_input" ,
"z" : "1a447be0.198674" ,
"name" : "Lon Manual" ,
"label" : "Longitude" ,
"tooltip" : "" ,
"group" : "7b7849e8.363288" ,
"order" : 6 ,
"width" : 12 ,
"height" : 1 ,
"passthru" : false ,
"mode" : "text" ,
"delay" : "2000" ,
"topic" : "longitude" ,
"x" : 650 ,
"y" : 500 ,
"wires" : [
[ ]
]
} ,
{
"id" : "34a51d85.680172" ,
"type" : "inject" ,
"z" : "1a447be0.198674" ,
"name" : "" ,
"props" : [
{
"p" : "payload"
}
] ,
"repeat" : "" ,
"crontab" : "" ,
"once" : true ,
"onceDelay" : 0.1 ,
"topic" : "" ,
"payload" : "false" ,
"payloadType" : "bool" ,
"x" : 130 ,
"y" : 420 ,
"wires" : [
[
"c05c94eb.25471" ,
"60308f41.f3b54"
]
]
} ,
{
"id" : "52ea7d01.711034" ,
"type" : "function" ,
"z" : "130e0533.4f1813" ,
"name" : "Encapsulate config" ,
"func" : "msg.payload = {\n \"action\":\"update_config\", \n \"config\":{\n \"sample_project\":global.get(\"sample_project\"),\n \"sample_id\":global.get(\"sample_id\"),\n \"sample_ship\":global.get(\"sample_ship\"),\n \"sample_operator\":global.get(\"sample_operator\"),\n \"sample_sampling_gear\":global.get(\"sample_sampling_gear\"),\n \n \"acq_id\":global.get(\"acq_id\"),\n \"acq_instrument\":global.get(\"acq_instrument\"),\n //\"acq_instrument_id\":global.get(\"acq_instrument_id\"),\n \"acq_celltype\":global.get(\"acq_celltype\"),\n \"acq_minimum_mesh\":global.get(\"acq_minimum_mesh\"),\n \"acq_maximum_mesh\":global.get(\"acq_maximum_mesh\"),\n \"acq_min_esd\":global.get(\"acq_min_esd\"),\n \"acq_max_esd\":global.get(\"acq_max_esd\"),\n \"acq_volume\":global.get(\"acq_volume\"),\n \"acq_magnification\":global.get(\"magnification\"),\n \"acq_fnumber_objective\":global.get(\"acq_fnumber_objective\"),\n \n \"acq_camera_name\":\"Pi Camera V2.1 - 8MP\",\n \n \"object_date\":global.get(\"object_date\"),\n \"object_time\":global.get(\"object_time\"),\n \"object_lat\":global.get(\"object_lat\"),\n \"object_lon\":global.get(\"object_lon\"),\n \"object_depth_min\":global.get(\"object_depth_min\"),\n \"object_depth_max\":global.get(\"object_depth_max\"),\n \n \"custom_nb_frame\":global.get(\"custom_nb_frame\"),\n \"custom_nb_step\":global.get(\"custom_nb_step\"),\n \"custom_segmentation\":global.get(\"custom_segmentation\"),\n \"custom_sleep_before\":global.get(\"custom_sleep_before\"),\n \"focus_nb_step\":global.get(\"focus_nb_step\"),\n \"pump_flowrate\":global.get(\"pump_flowrate\"),\n \"pump_manual_volume\":global.get(\"pump_manual_volume\"),\n \n \"process_pixel\":global.get(\"process_pixel\"),\n \"process_id\":global.get(\"process_id\")\n }\n};\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 430 ,
"y" : 60 ,
"wires" : [
[
"c3e50240.82aa58"
]
]
} ,
{
"id" : "40c12463.a1f84c" ,
"type" : "delay" ,
"z" : "130e0533.4f1813" ,
"name" : "" ,
"pauseType" : "delay" ,
"timeout" : "1" ,
"timeoutUnits" : "seconds" ,
"rate" : "1" ,
"nbRateUnits" : "1" ,
"rateUnits" : "second" ,
"randomFirst" : "1" ,
"randomLast" : "5" ,
"randomUnits" : "seconds" ,
"drop" : false ,
"x" : 400 ,
"y" : 100 ,
"wires" : [
[
"c9f510c0.7d1328"
]
]
} ,
{
"id" : "4d1b02cb.83b51c" ,
"type" : "ui_button" ,
"z" : "130e0533.4f1813" ,
"name" : "" ,
"group" : "4361c3b6.e2b7a4" ,
"order" : 10 ,
"width" : 0 ,
"height" : 0 ,
"passthru" : false ,
"label" : "Update config" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "" ,
"payload" : "" ,
"payloadType" : "str" ,
"topic" : "imager/image" ,
"x" : 200 ,
"y" : 60 ,
"wires" : [
[
"52ea7d01.711034"
]
]
} ,
{
"id" : "5a159d39.3bdca4" ,
"type" : "ui_text" ,
"z" : "bee3b478.ef4b88" ,
"group" : "91acd434.6205" ,
"order" : 3 ,
"width" : 6 ,
"height" : 1 ,
"name" : "imager" ,
"label" : "Imager status:" ,
"format" : "{{msg.payload.status}}" ,
"layout" : "col-center" ,
"x" : 870 ,
"y" : 200 ,
"wires" : [ ]
} ,
{
"id" : "89058790.909e7" ,
"type" : "ui_text" ,
"z" : "bee3b478.ef4b88" ,
"group" : "91acd434.6205" ,
"order" : 4 ,
"width" : 6 ,
"height" : 1 ,
"name" : "segmenter" ,
"label" : "Segmenter status:" ,
"format" : "{{msg.payload.status}}" ,
"layout" : "col-center" ,
"x" : 890 ,
"y" : 240 ,
"wires" : [ ]
} ,
{
"id" : "dc72e121.0aacd" ,
"type" : "ui_text" ,
"z" : "bee3b478.ef4b88" ,
"group" : "91acd434.6205" ,
"order" : 1 ,
"width" : 6 ,
"height" : 1 ,
"name" : "focus" ,
"label" : "Focus status:" ,
"format" : "{{msg.payload.status}}" ,
"layout" : "col-center" ,
"x" : 870 ,
"y" : 160 ,
"wires" : [ ]
} ,
{
"id" : "d700c8a1.2d1f48" ,
"type" : "ui_text" ,
"z" : "bee3b478.ef4b88" ,
"group" : "91acd434.6205" ,
"order" : 2 ,
"width" : 6 ,
"height" : 1 ,
"name" : "pump" ,
"label" : "Pump status:" ,
"format" : "{{msg.payload.status}}" ,
"layout" : "col-center" ,
"x" : 870 ,
"y" : 120 ,
"wires" : [ ]
} ,
{
"id" : "d95c87fe.e4ccd" ,
"type" : "ui_button" ,
"z" : "a0f9bde.423644" ,
"name" : "" ,
"group" : "de7c8e82.7faa98" ,
"order" : 1 ,
"width" : 3 ,
"height" : 1 ,
"passthru" : false ,
"label" : "UP 1mm" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "" ,
"payload" : "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}" ,
"payloadType" : "json" ,
"topic" : "actuator/focus" ,
"x" : 280 ,
"y" : 200 ,
"wires" : [
[
"a8dfcfd1.c5863"
]
]
} ,
{
"id" : "1be18c84.59a4ab" ,
"type" : "ui_button" ,
"z" : "a0f9bde.423644" ,
"name" : "" ,
"group" : "de7c8e82.7faa98" ,
"order" : 5 ,
"width" : 3 ,
"height" : 1 ,
"passthru" : false ,
"label" : "DOWN 1mm" ,
"tooltip" : "" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "" ,
"payload" : "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}" ,
"payloadType" : "json" ,
"topic" : "actuator/focus" ,
"x" : 270 ,
"y" : 240 ,
"wires" : [
[
"a8dfcfd1.c5863"
]
]
} ,
{
"id" : "d9930546.489a58" ,
"type" : "ui_slider" ,
"z" : "a0f9bde.423644" ,
"name" : "focus_distance" ,
"label" : "" ,
"tooltip" : "in µm" ,
"group" : "de7c8e82.7faa98" ,
"order" : 3 ,
"width" : 8 ,
"height" : 1 ,
"passthru" : true ,
"outs" : "end" ,
"topic" : "focus_distance" ,
"min" : "25" ,
"max" : "2000" ,
"step" : "25" ,
"x" : 540 ,
"y" : 100 ,
"wires" : [
[ ]
]
} ,
{
"id" : "4a30a6af.fa662" ,
"type" : "ui_switch" ,
"z" : "1a447be0.198674" ,
"d" : true ,
"name" : "Worldmap" ,
"label" : "Display worldmap" ,
"tooltip" : "" ,
"group" : "7b7849e8.363288" ,
"order" : 5 ,
"width" : 2 ,
"height" : 1 ,
"passthru" : true ,
"decouple" : "false" ,
"topic" : "" ,
"style" : "" ,
"onvalue" : "true" ,
"onvalueType" : "bool" ,
"onicon" : "" ,
"oncolor" : "" ,
"offvalue" : "false" ,
"offvalueType" : "bool" ,
"officon" : "" ,
"offcolor" : "" ,
"x" : 290 ,
"y" : 260 ,
"wires" : [
[
"60308f41.f3b54"
]
]
} ,
{
"id" : "60308f41.f3b54" ,
"type" : "function" ,
"z" : "1a447be0.198674" ,
"d" : true ,
"name" : "Enable" ,
"func" : "msg.enabled = msg.payload;\nmsg.payload = \"\"\n\nreturn msg;" ,
"outputs" : 1 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"x" : 440 ,
"y" : 260 ,
"wires" : [
[
"f7ae988c.184598"
]
]
} ,
{
"id" : "35ea3cf0.a398ac" ,
"type" : "exec" ,
"z" : "d95291dc.83b0b8" ,
"command" : "sudo killall -15 python3" ,
"addpay" : true ,
"append" : "" ,
"useSpawn" : "false" ,
"timer" : "" ,
"oldrc" : false ,
"name" : "Soft kill" ,
"x" : 1280 ,
"y" : 40 ,
"wires" : [
[ ] ,
[ ] ,
[ ]
]
} ,
{
"id" : "a776b9fc.d542e8" ,
"type" : "delay" ,
"z" : "d95291dc.83b0b8" ,
"d" : true ,
"name" : "" ,
"pauseType" : "delay" ,
"timeout" : "4" ,
"timeoutUnits" : "seconds" ,
"rate" : "1" ,
"nbRateUnits" : "1" ,
"rateUnits" : "second" ,
"randomFirst" : "1" ,
"randomLast" : "5" ,
"randomUnits" : "seconds" ,
"drop" : false ,
"x" : 700 ,
"y" : 100 ,
"wires" : [
[
"672d89a8.4e6968"
]
]
2020-01-08 14:32:46 +01:00
}
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.
All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.
Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.
Read along if you want to know all the goodies!
As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.
We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.
The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.
Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.
Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.
The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.
A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.
The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.
There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.
Here is the topic lists for MQTT and the corresponding messages.
- actuator : This topic adresses the stepper control thread
No publication under this topic should happen from the python process
- actuator/pump : Control of the pump
The message is a json object
{"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
to move 10mL forward at 1mL/min
action can be "move" or "stop"
Receive only
- actuator/focus : Control of the focus stage
The message is a json object, speed is optional
{"action":"move", "direction":"UP", "distance":0.26, "speed":1}
to move up 10mm
action can be "move" or "stop"
Receive only
- imager/image : This topic adresses the imaging thread
Is a json object with
{"action":"image","sleep":5,"volume":1,"nb_frame":200}
sleep in seconds, volume in mL
Can also receive a config update message:
{"action":"config","config":[...]}
Can also receive a camera settings message:
{"action":"settings","iso":100,"shutter_speed":40}
Receive only
- segmenter/segment : This topic adresses the segmenter process
Is a json object with
{"action":"segment"}
Receive only
- status : This topics sends feedback to Node-Red
No publication or receive at this level
- status/pump : State of the pump
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/focus : State of the focus stage
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Done, Interrupted
Publish only
- status/imager : State of the imager
Is a json object with
{"status":"Start", "time_left":25}
Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
Publish only
- status/segmenter : Status of the segmentation
- status/segmenter/name
- status/segmenter/object_id
- status/segmenter/metric
Here is the original commit history:
* Extract python main.py from flow
* Fix bug in server addresses
These addresses should be the loopback device instead of the network
address of the device. Using the loopback address will not necessitate
to update the script when the network address changes.
* clean up picamera import
* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location
* Automatically initialise imaging led on startup to off state.
* Add the ability to invert outputs of the motor
We added a key to config.json "hardware_config" with a subkey
"stepper_reverse". If this key is present in the config file and set to
1, the output of the motors are inversed (stepper2 becomes the pump
motor and stepper1 the focus motor)
* move all non main script to a subfolder
* add __init__.py to package
* light module rewrite
* json cleanup and absolute path for config file
* light.py forgot to import subprocess
#oups
* Add command to turn the leds off
* Auto formatting of main.py
I've used Black with default settings, see https://github.com/psf/black
* First commit of stepper.py
Pump parameters still needs to be checked and tuned.
* addition of hardware details in config.json
* Introduce hardware.json to replace the `hardware_config` of config.json
* stepper.py: calibration, typos
* creates the MQTT_Client class
* pump_max_speed is now in ml/min to help readability
* forgot to add self to the class def
* addition of threading capabilities to stepper.py (UNTESTED)
* mqtt: fix topic bug
* remove counter
* mqtt add doc about topics
* stepper.py creates an "actuator/*/state" topic
* stepper.py: rename mqtt_client to pump_client
* mqtt.py: add details about topics
* stepper.py: rename pump_client to actuator_client
* topic was not split properly and a part was lost
* switch to f-strings for mqtt.py
* cosmetic update
* stepper.py: folder name will be planktoscope change calls
* hardware.json became more straightforward
* stepper.py syntax bugs
* stepper.py addition of a received stop command
* stepper.py: update to max travel distance
* stepper.py: several typos here
* rename folder
* main.py: reword to reflect folder rename
* main.py: remove logic that has been moved to stepper.py and mqtt.py
* main.py: update to add mqtt imaging client
* mqtt.py: make command and args local to class and output more verbose
* make stepper.py a class
* main.py: instantiate stepper class and call it
* main.py: name mqtt client
* update to main.json to reflect main.py changes
* fix bugs around pump control
* update flows to latest version from Thibault
* distance can be a small value, and definitevely should be a float.
* unify mqtt topics
* unify mqtt output in the main flow
* first logger implementation, uses loguru
* mqtt: add reason to on_connect
* mqtt: add on_disconnect handler
* stepper: add more logger calls for debug mainly
* main: add levels for logger
* imager.py: first move of the imager logic
* imager: time import cleanup
* imager: morphocut import cleanup
* imager: skimage import cleanup
* imager: finishing import cleanup
* imager: Class creation - WIP
Also provides a fix for #26 (see line 190).
* imager: threading is needed for Condition()
* streamer: get the streamer server its own file
* imager: creates start_camera and get the server creation out
* imager: subclass multiprocessing.Process
* imager: get Pipeline creation its own function
* imager: cleanup of self calls
* main: code removal and corresponding calls to newly created classes
* imager: various formatting changes
* main: management of signal shutdown
* add requirements.txt
* mqtt: messages are now json objects
Also, addition of a flag on receiving a new message
* mqtt: make message private and add logic to synchronise
* stepper: creates the stepper class
* stepper: use the new class
* stepper: uses the new logic
* stepper: add the shutdown event
* stepper: add shutdown method
* main: add shutdown event
* imager: graceful shutdown
* stepper: nicer way of checking the Eevnt
* self is a required first argument for a method in a class
Especially if you use said class private members!
* python: various typos and small errors in import
* stepper: create mqtt client during init
* stepper: instanciate the mqtt client inside run
Otherwise it's not accessible from inside the loop. It's a PITA,
more information at https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class
* stepper: little bugs and typos all around
* mqtt: add shutdown method
* mqtt: add connect in init
* stepper: fix bugs, sanitize inputs
* stepper: work on delay prediction improvements
* stepper: json is mean, double quote are mandatory inside
* mqtt: add details about message exchanged
* imager: first implementation of json messages
* main.json: add new tab for RPi management + json for payloads
* imager: add state_machine class
* stepper: publish last will
* imager: major refactor
* main: make streaming server process a daemon
* mqtt: insert debug statement on close
* main: reorder imports
* imager: make it work!
Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global
Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise
* main: changes to accomodate the streamer/imager fusino
* imager_state_machine: insert states transition description
* stepper: cleanup of code
* segmenter: creation of the class
* python: include segmenter changes
* remove unused files
* stepper: check existence of hardware.json
* main.json: changes to reflect the python script evolution
* remove unecessary TODOs and add some others
* main: add check for config and directories
* imager: update_config is implemented and we have better management of directories now
* segmenter: now work recursively in all folders
* flow: the configuration is now sent via mqtt
* segmenter: better manage pipeline error
* segmenter: declaration of archive_fn in init
* imager: small bugs and typos
* main: add uniqueID output
* imager: add the camera settings message
We can now update the ISO, shutter speed and resolution from Node-Red
* package.json: update dependencies
2020-09-28 11:05:27 +02:00
]